POJ 1062 昂贵的聘礼 (最短路 Dijkstra)
昂贵的聘礼
昂贵的聘礼
大意:中文题
思路:每个物品看成一个节点,酋长的允诺也看作一个物品, 如果一个物品加上金币可以交换另一个物品,则这两个节点之间有边,权值为金币数,求第一个节点到所有节点的最短路。因为有等级限制,所以枚举每个点作为最低等级,选取符合所有符合等级限制的点。
PS:参考的别人的博客,理解的不是很透彻,有些地方没想明白,后面还是要复习一下。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #define INF 0x7FFFFFFF 5 6 int N, M; 7 ///物品i在有t号替代品的情况下的优惠价Map[i][t],当t=0时说明i无替代品,此时为原价 8 int Map[110][110]; 9 int dis[110]; ///最初的源点0到任意点i的最初距离(权值),相当于每个物品的原价 10 int level[110]; 11 int x[110]; 12 bool vis[110]; 13 14 int Dijkstra() 15 { 16 int p; 17 int Min_d; 18 for(int i = 1; i <= N; i++) 19 { 20 ///假设最初的源点就是0点,初始化最初源点到各点的权值dis[i] 21 dis[i] = Map[0][i]; 22 } 23 for(int i = 1; i <= N; i++) 24 { 25 p = 0; 26 Min_d = INF; 27 for(int j = 1; j <= N; j++) 28 { 29 if(!vis[j] && Min_d >dis[j]) 30 { 31 Min_d = dis[j]; 32 p = j; 33 } 34 } 35 if(!p) 36 { 37 break; 38 } 39 vis[p] = true; 40 for(int j = 1; j <= N; j++) 41 { 42 ///把未访问但与新源点连通的点进行松弛 43 if(!vis[j] && Map[p][j] > 0 &&dis[j] > dis[p]+Map[p][j]) 44 { 45 dis[j] = dis[p]+Map[p][j]; 46 } 47 } 48 } 49 ///返回当前次交易后目标点1在等级level[i]约束下的最短距离 50 return dis[1]; 51 } 52 53 void Solve() 54 { 55 memset(Map, 0, sizeof(Map)); 56 memset(level, 0, sizeof(level)); 57 memset(vis, false, sizeof(vis)); 58 memset(dis, INF, sizeof(dis)); 59 scanf("%d%d", &M, &N); 60 for(int i = 1; i <= N; i++) 61 { 62 ///Map[0][i]为物品i无替代品时的原价 63 scanf("%d%d%d", &Map[0][i], &level[i], &x[i]); 64 for(int j = 1; j <= x[i]; j++) 65 { 66 int t, u; 67 scanf("%d%d", &t, &u); 68 Map[t][i] = u; 69 } 70 } 71 int Max_level; 72 int Min_price = INF; 73 for(int i = 1; i <= N; i++) 74 { 75 Max_level = level[i];///把当前物品的等级暂时看做最高等级 76 for(int j = 1; j <= N; j++) 77 { 78 if(level[j] > Max_level || Max_level-level[j] > M) 79 vis[j] = true; 80 else 81 vis[j] = false; 82 } 83 int t = Dijkstra(); 84 if(Min_price > t) 85 Min_price = t; 86 } 87 printf("%d\n", Min_price); 88 } 89 90 int main() 91 { 92 Solve(); 93 94 return 0; 95 }