POJ1062 昂贵的聘礼 单源最短路径变形 dijkstra算法

转自:http://blog.csdn.net/yangliuy/article/details/7173287


思路:以物品为结点,物品之间的优惠价格为边权值建图,酋长10000金币当做0号结点,题意就是求图中各结点到0号结点的最短路长度,再加上终点处物品的价值,恰好就是探险家经过这个物品买卖途径所需要付出的金钱。用dijkstra算法求出单源最短路径,从各个结点的最短路径中选出最短的那条就是答案。基本还是经典最短路问题,但做了一点小小变形主要是:

1 有结点等级限制,需要枚举等级 

2 把终点的物品价值计入最短路径中去,并且找最小的最短路径输出

3 要注意是单向图,即物品替换关系是单向的

Source Code

Problem: 1062 User: yangliuACMer
Memory: 300K Time: 32MS
Language: C++ Result: Accepted
[cpp]  view plain copy
  1. #include <iostream>  
  2. #define MAXN 102  
  3. #define inf 100000000  
  4. typedef int elem_t;  
  5. using namespace std;  
  6. struct Thing{  
  7.     int val;//该物品价值  
  8.     int level;//该物品主人等级  
  9.     int replacen;//替换品数量  
  10. } things[MAXN];  
  11.   
  12. int m,n,nonum,noval,s,mat[MAXN][MAXN],dist[MAXN],lev[MAXN],levn;  
  13. int i,j,p,k;  
  14.   
  15. int dijkstra(int n,elem_t mat[][MAXN],int s){  
  16.     int v[MAXN], maxlev, minlev;  
  17.     int ans = things[0].val;      
  18.     //枚举等级  
  19.     for(p = 0; p < levn; p++){  
  20.         maxlev = lev[p];  
  21.         minlev = lev[p]-m;  
  22.         if(things[0].level < minlev || things[0].level > maxlev) continue;  
  23.         for (i = 0 ;i < n ;i++)  
  24.             dist[i] = inf,v[i] = 0;  
  25.         for (dist[s] = 0,j = 0; j < n; j++){  
  26.             for (k = -1,i = 0; i < n; i++)  
  27.                 if (!v[i] && (k == -1|| dist[i] < dist[k])&&(things[i].level >= minlev && things[i].level <= maxlev))  
  28.                     k=i;  
  29.             for (v[k] = 1,i = 0 ;i < n; i++)  
  30.                 if (!v[i] && dist[k] + mat[k][i] < dist[i] && (things[i].level >= minlev && things[i].level <= maxlev))  
  31.                     dist[i] = dist[k] + mat[k][i];  
  32.         }  
  33.         //把终点的val计入最短路径中去,并且找最小的最短路径输出  
  34.         for(j=0; j<n; j++)   
  35.             dist[j] += things[j].val;  
  36.         for(j=0; j<n; j++)   
  37.             if(dist[j]<ans)   
  38.                 ans = dist[j];  
  39.     }  
  40.     return ans;  
  41. }  
  42.   
  43. int main(){  
  44.     //读入数据建图,邻接矩阵形式  
  45.     cin>>m>>n;  
  46.     for(i = 0; i < n; i++)   
  47.         for(j = 0; j<n ; j++)  
  48.             mat[i][j] = inf;  
  49.     levn = 0;  
  50.     for(i = 0; i < n; i++){  
  51.         cin>>things[i].val>>things[i].level>>things[i].replacen;  
  52.         lev[levn++] = things[i].level;//记录所有物品的等级  
  53.         for(j = 0; j < things[i].replacen; j++){  
  54.             cin>>nonum>>noval;  
  55.             mat[i][nonum-1] = noval;//注意是单向图  
  56.         }  
  57.     }  
  58.     cout<<dijkstra(n,mat,0)<<endl;  
  59.     return 0;     
  60. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值