poj 2267 From Dusk till Dawn or: Vladimir the Vampire

poj 2267 From Dusk till Dawn or: Vladimir the Vampire

有个吸血鬼要从城市 A 到城市 B, 但是吸血鬼有 3 个问题需要克服:他只能在傍晚 18:00 到凌晨 6:00 之间旅行,其他时间只能待在车站。二:他必须带一个盒子,盒子里面装的血。三:他每天中午 12 点需要喝盒子里面的 1 升血。

问题:你帮吸血鬼找到一条路径,它需要带最少的血。

输入: n :道路的条数

每条路包括:起始城市,终点城市,起始时间,所需要的时间

输出:如果能找到路径则输出最少量的血。

题目是个单源最短路径题目,最开始想用 prim 算法解决,然后开始写程序,写到中途觉得不太对了, route A->B ),如果存在很多条需要血量一样的道路,到底保存哪一条呢?保存起始时间最晚的,还是到达时间最早的;因为这两种情况都有可能是最优情况的候选。

后来就想的比较愚笨的方法,不就是要找一条路么?我把所有的路遍历,终归能够找到那条需要的路吧,所以我选择了深度搜索算法。

先进行预处理,把那些吸血鬼没办法走的路去掉,然后把城市用数字编号表示。吸血鬼只能在 18:00-6:00 之间进行旅行,这个时间段处理起来很麻烦,所以我把它全部加 6 ,这样子时间就变成了 0:00-12:00 ,这样子,只要到达时间 <= 出发时间就不用喝血了,否则就需要喝。

预处理完成,保存每条吸血鬼有可能走的路,按照以下数据结构。

struct {

int citys;// 起点城市

int citye;// 终点城市

int start;// 起始时间

int cost;// 路上花费的时间

}road[NUMR];NUMR 最大的路数

然后搜索到可能到的城市,保存吸血鬼的状态,按照以下数据结构

struct {

int arrive;// 到达时间

int litre;// 到达城市i 需要的血量

}blood[NUMC];//NUMC 最大的城市数

如果到达的时间晚于出发的时间,则需要+1 的血量。

#include <iostream>

#include <stdio.h>

#include <string>

using namespace std;

#define NUMC 103

#define NUMR 1005

#define NUMN 35

#define INF 1000000

struct {

int citys;

int citye;

int start;

int cost;

}road[NUMR];

struct {

int arrive;

int litre;

}blood[NUMC];

char city[NUMC][NUMN];

int numR,numC,ans;//numR 表示路径的条数,numC 表示出现过的城市数

void DFS(int src,int dst)

{

     if (src==dst)// 找到目的城市,则返回

     {

         if (blood[src].litre<ans)

              ans=blood[src].litre;

         return ;

     }

     if (blood[src].litre>=ans)// 未到目的城市,可是这条路没办法找到更优的结果,则返回

         return ;

     for (int i=0;i<numR;i++)// 找到以src 为起点城市的路,然后进行旅行

         if (road[i].citys==src&&blood[road[i].citys].litre+1<=blood[road[i].citye].litre)

         {

              blood[road[i].citye].arrive=road[i].start+road[i].cost;

              if (blood[road[i].citys].arrive<=road[i].start)// 到达的时间晚于出发的时间,就需要喝血了

                   blood[road[i].citye].litre=blood[road[i].citys].litre;

              else

                   blood[road[i].citye].litre=blood[road[i].citys].litre+1;

              DFS(road[i].citye,dst);

 

 

         }

         return ;

}

 

int main()

{

     int cases,times=0;

     scanf(“%d” ,&cases);

     while (cases–)

     {

         int i,j,n,start,cost,t1,t2;

         numR=0;

         numC=0;

         char city1[NUMN],city2[NUMN];

         scanf(“%d” ,&n);

         for (i=0;i<n;i++)// 对城市进行预处理,把它用数字表示

         {

              scanf(“%s%s%d%d” ,city1,city2,&start,&cost);

              start=(start+6)%24;// 预处理时间,将其旅行时间变为0:00-12:00

              if (start+cost<=12)// 如果吸血鬼不能在0:00-12:00 之间完成旅行,则舍去这条路

              {

                   t1=-1;

                   t2=-1;

                   for (j=0;j<numC;j++)

                   {

                       if (strcmp(city1,city[j])==0)

                            t1=j;

                       if (strcmp(city2,city[j])==0)

                            t2=j;

                   }

                   if (t1==-1)// 起点城市未出现过

                   {

                        strcpy(city[numC],city1);

                       t1=numC;

                       numC++;

                   }

                   if (t2==-1)// 终点城市未出现过

                   {

                       strcpy(city[numC],city2);

                       t2=numC;

                       numC++;

                   }

                   road[numR].citys=t1;

                   road[numR].citye=t2;

                   road[numR].cost=cost;

                   road[numR].start=start;

                   numR++;

              }

         }

         scanf(“%s%s” ,city1,city2);

         t1=-1;

         t2=-1;

         for (i=0;i<numC;i++)

         {

              if (strcmp(city1,city[i])==0)

                   t1=i;

              if (strcmp(city2,city[i])==0)

                   t2=i;                 

         }

         printf(“Test Case %d./n” ,++times);

         if (t1==-1||t2==-1)// 如果起点城市或者终点城市不在路径出现的城市中,则不可能找到路

         {

              printf(“There is no route Vladimir can take./n” );

              continue ;

         }

         for (i=0;i<numC;i++)

         {

              blood[i].arrive=0;

              blood[i].litre=INF;

         }

         ans=INF;

         blood[t1].litre=0;

         DFS(t1,t2);

         if (ans!=INF)

              printf(“Vladimir needs %d litre(s) of blood./n” ,ans);

         else

              printf(“There is no route Vladimir can take./n” );

 

     }

     return 0;

}

点赞