poj1724——ROADS

来源:互联网 发布:身份证合成软件 编辑:程序博客网 时间:2024/06/06 19:44

题目:Bob想从城市1去城市N,这些城市间有一些长度和花费不同的路共R条,两个城市之间可以有很多路(单向路),Bob只有K枚硬币,问他的最短路径

输入:K(0 <= K <= 10000)

           N(2 <= N <= 100)

           R(1 <= R <= 10000)

           第i条路的描述(共R行,S D L T分别代表起点、终点、路长( 1 <= L <= 100 )、开销(0 <= T <=100))

输出:最短路径长度(如果不存在输出-1)

分析:dfs+剪枝/bfs+优先级队列

代码:转载自http://blog.csdn.net/riba2534/article/details/70169857

以下是dfs+剪枝的方法:

  1. #include <cstdio>  
  2. #include <cstring>    
  3. #include <algorithm>  
  4. #define mem(a,b) memset(a,b,sizeof(a))  
  5. #define inf 0x3f3f3f3f   
  6. #define N 100+20  
  7. #define M 1000000+10 
  8. using namespace std;  
  9. int first[N], vis[N];  
  10. int k,n,m,len,sum;  
  11. struct node  
  12. {  
  13.     int u,v,w,cost;  
  14.     int next;  
  15. } g[10200];  
  16. void add_edge(int u,int v,int w,int cost)//邻接表建图  
  17. {  
  18.     g[len].v=v;  
  19.     g[len].w=w;  
  20.     g[len].cost=cost;  
  21.     g[len].next=first[u];  
  22.     first[u]=len++;  
  23. }  
  24. void dfs(int x,int step,int cost)//当前城市x  当前距离step  当前花费cost
  25. {  
  26.     if(cost>k||step>sum)//剪枝条件,花费大于拥有的钱数和步数大于当前最小的步数  
  27.         return;  
  28.     if(x==n)  
  29.         sum=min(sum,step);//更新步数最小值  
  30.     for(int i=first[x]; i!=-1; i=g[i].next)  
  31.     {  
  32.         int v=g[i].v;  
  33.         if(!vis[v])  
  34.         {  
  35.             vis[v]=1;  
  36.             dfs(v,step+g[i].w,cost+g[i].cost);  
  37.             vis[v]=0;  
  38.         }  
  39.     }  
  40. }  
  41. int main()  
  42. {  
  43.     len=0;  
  44.     int a,b,c,d;  
  45.     mem(vis,0);  
  46.     mem(first,-1);  
  47.     scanf("%d%d%d",&k,&n,&m);  
  48.     for(int i=0; i<m; i++)  
  49.     {  
  50.         scanf("%d%d%d%d",&a,&b,&c,&d);  
  51.         add_edge(a,b,c,d);  
  52.     }  
  53.     sum=inf;  
  54.     dfs(1,0,0);  
  55.     if(sum==inf)  
  56.         puts("-1");  
  57.     else  
  58.         printf("%d\n",sum);  
  59.     return 0;  
  60. }
以下是优先级队列的方法:(改进的dijkstra)

  1. #include <cstdio>  
  2. #include <cstring>   
  3. #include <queue>  
  4. #include <algorithm>  
  5. #define mem(a,b) memset(a,b,sizeof(a))  
  6. #define inf 0x3f3f3f3f  
  7. #define N 100+20  
  8. #define M 1000000+10  
  9. using namespace std;  
  10. int k,n,m,len,sum;  
  11. int first[N],dis[N][10005];  
  12. struct node1  
  13. {  
  14.     int v,dis,cost,next;  
  15. } g[10010];  
  16. struct node  
  17. {  
  18.     int num,dis,cost;  
  19.     bool friend operator < (node a,node b)//重载运算符  
  20.     {  
  21.         return a.dis>b.dis;  
  22.     }  
  23. };  
  24. void add_edge(int u,int v,int dis,int cost)//邻接表建图  
  25. {  
  26.     g[len].v=v;  
  27.     g[len].dis=dis;  
  28.     g[len].cost=cost;  
  29.     g[len].next=first[u];  
  30.     first[u]=len++;  
  31. }  
  32. void dijkstra()  
  33. {  
  34.     for(int i=1; i<=n; i++)  
  35.         for(int j=0; j<=k; j++)  
  36.             dis[i][j]=inf;//dis[i][j]表示从点1到点i花费的钱数为j的最短距离  
  37.     dis[1][0]=0;  
  38.     priority_queue<node>q;  
  39.     node now,to;  
  40.     now.num=1;  
  41.     now.cost=0;  
  42.     now.dis=0;  
  43.     q.push(now);  
  44.     while(!q.empty())  
  45.     {  
  46.         now=q.top();  
  47.         q.pop();  
  48.         if(now.num==n)//找到的时候直接输出并返回  
  49.         {  
  50.             printf("%d\n",now.dis);  
  51.             return;  
  52.         }  
  53.         for(int i=first[now.num]; i!=-1; i=g[i].next)  
  54.         {  
  55.             int cost=now.cost+g[i].cost;  
  56.             if(cost>k)continue;  
  57.             if(dis[g[i].v][cost]>now.dis+g[i].dis)//松弛条件  
  58.             {  
  59.                 dis[g[i].v][cost]=now.dis+g[i].dis;  
  60.                 to.num=g[i].v;  
  61.                 to.cost=cost;  
  62.                 to.dis=dis[g[i].v][cost];  
  63.                 q.push(to);  
  64.             }  
  65.         }  
  66.     }  
  67.     puts("-1");  
  68. }  
  69. int main()  
  70. {  
  71.     len=0;  
  72.     int a,b,c,d;  
  73.     mem(first,-1);  
  74.     scanf("%d%d%d",&k,&n,&m);  
  75.     for(int i=0; i<m; i++)  
  76.     {  
  77.         scanf("%d%d%d%d",&a,&b,&c,&d);  
  78.         add_edge(a,b,c,d);  
  79.     }  
  80.     dijkstra();  
  81.     return 0;  
  82. }


原创粉丝点击