[题解]UVA10801 Lift Hopping

链接:http://vjudge.net/problem/viewProblem.action?id=22172

描述:有n部电梯,每部电梯都有不能停下的楼层,要求搭乘电梯从第0层到第k层。

思路:单源点最短路

        建图:将每层楼拆成n个点,用边权解决换乘等待的时间。将每部电梯能到达的楼层顺次连接,边权是该电梯经过所需时间。最后建立一个超级源点S,连接每部电梯的第0层的节点,边权为0,方便统计答案。

 

下面是我的实现,Dijkstra版本:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <queue>
  5 using namespace std;
  6 #define MaxN 520
  7 #define MaxM 3020
  8 #define Max_n 8
  9 #define S 500
 10 #define INF 100000
 11 struct node
 12 {
 13     int v,dist;
 14     node *next;
 15 };
 16 node Edge[MaxM];
 17 node *cnt=&Edge[0];
 18 node *adj[MaxN];
 19 int dist[MaxN];
 20 int T[Max_n];
 21 int n,K,Ans;
 22 bool For_Build[MaxN];
 23 inline void Clean()
 24 {
 25     memset(Edge,0,sizeof(Edge));
 26     cnt=&Edge[0];
 27     memset(adj,0,sizeof(adj));
 28 }
 29 inline void Addedge(int u,int v,int w)
 30 {
 31     node *p=++cnt;
 32     p->v=v;
 33     p->dist=w;
 34     p->next=adj[u];
 35     adj[u]=p;
 36 
 37     p=++cnt;
 38     p->v=u;
 39     p->dist=w;
 40     p->next=adj[v];
 41     adj[v]=p;
 42 }
 43 inline void Read_Build()
 44 {
 45     int i,j,Num,f1,f2;
 46     for(i=1;i<=n;i++)
 47         scanf("%d",&T[i]);
 48     for(i=1;i<=n;i++)
 49     {
 50         Num=100*(i-1);
 51         Addedge(S,Num,0);
 52         f1=-1;
 53         do
 54         {
 55             scanf("%d",&f2);For_Build[Num+f2]=true;
 56             if(f1!=-1)
 57                 Addedge(Num+f1,Num+f2,(f2-f1)*T[i]);
 58             f1=f2;
 59             for(j=1;j<i;j++)
 60                 if(For_Build[100*(j-1)+f2])
 61                     Addedge(100*(j-1)+f2,Num+f2,60);
 62         }while(getchar()!='\n');
 63     }
 64 }
 65 struct cmp
 66 {
 67     bool operator()(node a,node b)
 68     {
 69         return a.dist>b.dist;
 70     }
 71 };
 72 priority_queue <node, vector<node>, cmp> q;
 73 void Dijkstra(int s)
 74 {
 75     node c,d;
 76     node *p;
 77     int i,j,k;
 78     memset(dist,0x3f,sizeof(dist));
 79     dist[s]=0;
 80     c.v=s;c.dist=0;
 81     q.push(c);
 82     while(!q.empty())
 83     {
 84         d=q.top();q.pop();
 85         j=d.v;
 86         for(p=adj[j];p!=NULL;p=p->next)
 87         {
 88             k=p->v;
 89             if(dist[k]>dist[j]+p->dist)
 90             {
 91                 dist[k]=dist[j]+p->dist;
 92                 d.v=k;d.dist=dist[k];
 93                 q.push(d);
 94             }
 95         }
 96     }
 97 }
 98 inline void Print()
 99 {
100     int i;
101     for(i=1;i<=n;i++)
102         Ans=min(Ans,dist[100*(i-1)+K]);
103     if(Ans==INF)
104         printf("IMPOSSIBLE\n");
105     else
106         printf("%d\n",Ans);
107 }
108 int main()
109 {
110     while(scanf("%d%d",&n,&K)!=EOF)
111     {
112         Clean();
113         Read_Build();
114         Dijkstra(S);
115         Ans=INF;
116         Print();
117     }
118     return 0;
119 }
View Code

 我是用拆点的方法解决换乘等待的时间问题的,在网上看到另一种处理方式感觉很科学。本以为我的会很慢,实践证明还是算比较快的了,也可能是数据不强。

然后我再试了试spfa,稍微慢一点:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <queue>
  5 using namespace std;
  6 #define MaxN 520
  7 #define MaxM 3020
  8 #define Max_n 8
  9 #define S 500
 10 #define INF 100000
 11 struct node
 12 {
 13     int v,dist;
 14     node *next;
 15 };
 16 node Edge[MaxM];
 17 node *cnt=&Edge[0];
 18 node *adj[MaxN];
 19 int dist[MaxN];
 20 int T[Max_n];
 21 int n,K,Ans;
 22 bool For_Build[MaxN],vis[MaxN];
 23 inline void Clean()
 24 {
 25     memset(Edge,0,sizeof(Edge));
 26     cnt=&Edge[0];
 27     memset(adj,0,sizeof(adj));
 28 }
 29 inline void Addedge(int u,int v,int w)
 30 {
 31     node *p=++cnt;
 32     p->v=v;
 33     p->dist=w;
 34     p->next=adj[u];
 35     adj[u]=p;
 36 
 37     p=++cnt;
 38     p->v=u;
 39     p->dist=w;
 40     p->next=adj[v];
 41     adj[v]=p;
 42 }
 43 inline void Read_Build()
 44 {
 45     int i,j,Num,f1,f2;
 46     for(i=1;i<=n;i++)
 47         scanf("%d",&T[i]);
 48     for(i=1;i<=n;i++)
 49     {
 50         Num=100*(i-1);
 51         Addedge(S,Num,0);
 52         f1=-1;
 53         do
 54         {
 55             scanf("%d",&f2);For_Build[Num+f2]=true;
 56             if(f1!=-1)
 57                 Addedge(Num+f1,Num+f2,(f2-f1)*T[i]);
 58             f1=f2;
 59             for(j=1;j<i;j++)
 60                 if(For_Build[100*(j-1)+f2])
 61                     Addedge(100*(j-1)+f2,Num+f2,60);
 62         }while(getchar()!='\n');
 63     }
 64 }
 65 queue<int>q;
 66 void Spfa(int s)
 67 {
 68     int j,k;
 69     memset(dist,0x3f,sizeof(dist));
 70     dist[s]=0;
 71     q.push(s);
 72     vis[s]=true;
 73     while(!q.empty())
 74     {
 75         j=q.front();
 76         q.pop();
 77         vis[j]=false;
 78         for(node *p=adj[j];p!=NULL;p=p->next)
 79         {
 80             k=p->v;
 81             if(dist[k]>dist[j]+p->dist)
 82             {
 83                 dist[k]=dist[j]+p->dist;
 84                 if(!vis[k])
 85                 {
 86                     q.push(k);
 87                     vis[k]=true;
 88                 }
 89             }
 90         }
 91     }
 92 }
 93 inline void Print()
 94 {
 95     int i;
 96     for(i=1;i<=n;i++)
 97         Ans=min(Ans,dist[100*(i-1)+K]);
 98     if(Ans==INF)
 99         printf("IMPOSSIBLE\n");
100     else
101         printf("%d\n",Ans);
102 }
103 int main()
104 {
105     while(scanf("%d%d",&n,&K)!=EOF)
106     {
107         Clean();
108         Read_Build();
109         Spfa(S);
110         Ans=INF;
111         Print();
112     }
113     return 0;
114 }
View Code

posted @ 2014-07-04 18:02  zyy是一只超级大沙茶  阅读(224)  评论(0编辑  收藏  举报