POJ_1062_昂贵的聘礼(最短路)
/*
这道题关键是解决怎么存储的问题和那个等级限制的处理。把物品看成是N个点
N个点的d[]初始值便是他们的价值。
map[i][j];代表物品i和物品j进行交换需要的钱数。
dijkstra算法:每次选择d值最小的节点x;
具体解释见代码。
*/
# i
1 # include <stdio.h> 2 # include <string.h> 3 # define inf 100000000 4 int map[110][110]; //map[i][j]代表物品i与j交换的钱数; 5 int value[110],level[110];//物品的价值,等级水平。 6 int n,m,vis[110]; //vis用于标记是否访问过。 7 int d[110]; //记录最小花费。 8 int dijkstra(int x) 9 { 10 int i,j,k,min; 11 memset(vis,0,sizeof(vis)); 12 d[0]=0;vis[0]=1;//源点d赋值成0 13 for(i=1;i<=n;i++) 14 d[i]=map[0][i];//每个物品赋值成它的价值; 15 for(i=1;i<=n;i++) //循环n次肯定能找到最短路。 16 { 17 min=inf; 18 for(j=0;j<=n;j++) //寻找结点当中值最小的,记录下标和最小值。 19 { 20 if(!vis[j] && d[j]<min) 21 { 22 min=d[j]; 23 k=j; 24 } 25 } 26 if(min == inf) //说明没有连通的边,或者已经都找完
27 break; 28 vis[k]=1; //标记被访问过。 29 for(j=0;j<=n;j++)//进行一次修改结点值操作,修改成源节点和k结点中最小的那一个; 30 {// k件物品加交换钱数比j物品的价值小才交换,前提是在允许的等级之内。 31 if(!vis[j] && d[j]>d[k]+map[k][j] && level[k]<=x+m &&level[k]>=x) 32 d[j]=d[k]+map[k][j]; 33 } 34 35 } 36 return d[1];//n次修改完了之后,d[1]保存的就是结果。 37 } 38 int main() 39 { 40 int i,j,k,x,price,id; 41 while(scanf("%d%d",&m,&n) != EOF) 42 { 43 for(i=0;i<=100;i++) 44 { 45 map[i][i]=0; 46 for(j=i+1;j<=100;j++) 47 { 48 map[i][j]=map[j][i]=inf; 49 } 50 } 51 52 for(i=1;i<=n;i++) 53 { 54 scanf("%d%d%d",&value[i],&level[i],&x); 55 for(j=1;j<=x;j++) 56 { 57 scanf("%d%d",&id,&price); 58 map[id][i]=price; 59 } 60 } 61 for(i=1;i<=n;i++) 62 map[0][i]=value[i]; 63 level[0]=level[1]; 64 int low=level[1]-m; 65 int ans=inf; 66 for(i=low;i<=level[1];i++) 67 { 68 int temp=dijkstra(i); 69 if(temp<ans) 70 ans=temp; 71 } 72 73 printf("%d\n",ans); 74 } 75 return 0; 76 77 }