poj 1062 昂贵的聘礼

题目链接:

  http://poj.org/problem?id=1062

题目意思:

  中文题目,我就不再废话了。但是有一点要提醒的是在整个交易网中,参加交易的人的最高级别和最低级别差不能超过m,而不是与相邻交易的级别差不超过m,经过一下午的纠结以后,血淋淋的教训告诉我们以后读题目一定要认真,写代码之前要思考,思考时候要慎重。

解题思路:

  本题最重要的是要想清楚怎么建造图更合适。

  1:我们可以建造一个0点代表虚拟的原点,把1当成终点,以此转化为求到1的最短路。

  2:交换是有方向的,只能单向交换,要建立有向图。

  3:一个合法的交易链中,级别最高级别和最低级别差别不能超过m。

  4:起点不能确定,所以要枚举比较得出最短。

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <algorithm>
 6 #include <iostream>
 7 using namespace std;
 8 #define maxn 110
 9 #define INF 0x3f3f3f3f
10 
11 struct node
12 {
13     int val[maxn];//可以与之交换的物品的价格
14     int num[maxn];//可以与之交换的物品的编号
15     int p, l, x;
16 }goods[maxn];
17 
18 int map[maxn][maxn], n, m;
19 void init ();
20 int dijk (int x);//用dijkstra求最短路
21 
22 int main ()
23 {
24     int i, j;
25     while (scanf ("%d %d", &m, &n) != EOF)
26     {
27         init ();
28         memset (goods, 0, sizeof(goods));
29         for (i=1; i<=n; i++)
30         {
31             scanf ("%d %d %d", &goods[i].p, &goods[i].l, &goods[i].x);
32             map[0][i] = goods[i].p;//设定一个虚拟的原点,避免所建图中没有边,无法进行计算
33             for (j=0; j<goods[i].x; j++)
34                 scanf ("%d %d", &goods[i].num[j], &goods[i].val[j]);
35         }
36         for (i=1; i<=n; i++)
37             for (j=0; j<goods[i].x; j++)
38                 if (abs(goods[goods[i].num[j]].l - goods[i].l) <= m && map[goods[i].num[j]][i] > goods[i].val[j])
39                 {//在合法的等级范围内建边,并且尽量建立最短的边
40                         map[goods[i].num[j]][i] = goods[i].val[j];
41                 }
42 
43         int mi = INF;
44         for (i=1; i<=n; i++)//对所有有效的等级进行遍历
45             mi = min (mi, dijk(i));
46         printf ("%d
", mi);
47     }
48     return 0;
49 }
50 
51 void init ()
52 {
53     int i, j;
54     for (i=0; i<=n; i++)
55         for (j=0; j<=n; j++)
56             map[i][j] = INF;
57 }
58 
59 int dijk (int x)
60 {
61     int dist[maxn], vis[maxn], i, j;
62     int high = goods[x].l + m;//等级最大值
63     int low = goods[x].l;//等级最小值
64     memset (vis, 0, sizeof(vis));
65     for (i=0; i<=n; i++)//在有效等级内初始化为有效值,否则为INF
66         if (low <= goods[i].l && goods[i].l <= high)
67             dist[i] = map[0][i];
68         else
69             dist[i] = INF;
70 
71     vis[0] = 1;
72 
73     for (j=0; j<n; j++)
74     {
75         int mi = INF, index;
76         for (i=0; i<=n; i++)
77         {//因为无效等级的dist为INF,不需要对点的等级判断
78             if (!vis[i] && dist[i] < mi)
79             {
80                 mi = dist[i];
81                 index = i;
82             }
83         }
84         if (mi == INF)
85             break;//图中各点有可能不是联通的,会造成下一步数组越界
86         vis[index] = 1;
87 
88         for (i=0; i<=n; i++)//加入最优点以后,对现有边进行松弛
89         if (!vis[i] && low<=goods[i].l && goods[i].l <=high && map[index][i] + dist[index] < dist[i])
90             dist[i] = dist[index] + map[index][i];
91     }
92     return dist[1];
93 }
本文为博主原创文章,未经博主允许不得转载。
原文地址:https://www.cnblogs.com/alihenaixiao/p/4229542.html