最短路----求满足两个条件的情况

 1 7-3 打怪升级
 2 分数 25
 3 作者 陈越
 4 单位 浙江大学
 5 dgsj.JPG
 6 
 7 很多游戏都有打怪升级的环节,玩家需要打败一系列怪兽去赢取成就和徽章。这里我们考虑一种简单的打怪升级游戏,游戏规则是,给定有 N 个堡垒的地图,堡垒之间有道路相连,每条道路上有一只怪兽把守。怪兽本身有能量,手里的武器有价值。打败怪兽需要的能量等于怪兽本身的能量,而怪兽一旦被打败,武器就归玩家所有 —— 当然缴获的武器价值越高,玩家就越开心。
 8 
 9 你的任务有两件:
10 
11 帮助玩家确定一个最合算的空降位置,即空降到地图中的某个堡垒,使得玩家从这个空降点出发,到攻下最难攻克(即耗费能量最多)的那个堡垒所需要的能量最小;
12 从这个空降点出发,帮助玩家找到攻克任意一个其想要攻克的堡垒的最省能量的路径。如果这种路径不唯一,则选择沿途缴获武器总价值最高的解,题目保证这种解是唯一的。
13 输入格式:
14 输入第一行给出两个正整数 N (≤1000) 和 M,其中 N 是堡垒总数,M 是怪兽总数。为简单起见,我们将堡垒从 1 到 N 编号。随后 M 行,第 i 行给出了第 i 只怪兽的信息,格式如下:
15 
16 B1 B2 怪兽能量 武器价值
17 其中 B1 和 B2 是怪兽把守的道路两端的堡垒编号。题目保证每对堡垒之间只有一只怪兽把守,并且 怪兽能量 和 武器价值 都是不超过 100 的正整数。
18 
19 再后面是一个正整数 K(≤N)和玩家想要攻克的 K 个目标堡垒的编号。
20 
21 输出格式:
22 首先在一行中输出玩家空降的堡垒编号 B0。如果有多种可能,则输出编号最小的那个。
23 
24 随后依次为玩家想要攻克的每个堡垒 B 推荐最省能量的攻克路径,并列出需要耗费的能量值和沿途缴获武器的总价值。注意如果最省力的路径不唯一,则选择沿途缴获武器总价值最高的解。格式为:
25 
26 B0->途经堡垒1->...->B
27 总耗费能量 武器总价值
28 输入样例:
29 6 12
30 1 2 10 5
31 2 3 16 20
32 3 1 4 2
33 2 4 20 22
34 4 5 2 2
35 5 3 12 6
36 4 6 8 5
37 6 5 10 5
38 6 1 20 25
39 1 5 8 5
40 2 5 2 1
41 2 6 8 5
42 4
43 2 3 6 5
44 输出样例:
45 5
46 5->2
47 2 1
48 5->1->3
49 12 7
50 5->4->6
51 10 7
52 5
53 0 0
54 代码长度限制

这道题的难点:

从这个空降点出发,帮助玩家找到攻克任意一个其想要攻克的堡垒的最省能量的路径。如果这种路径不唯一,则选择沿途缴获武器总价值最高的解,题目保证这种解是唯一的。
接下来是我认为我至今写的最好的Dijkstra算法,建议以后以这个为模板:
  1 #include <iostream>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <stack>
  5 using namespace std;
  6 const int N = 1010, INF = 0x3f3f3f3f;
  7 struct node
  8 {
  9     int power = INF, value = 0;
 10 } g[N][N];        // Dijkstra要
 11 int gg[N][N], B0; // floyd要
 12 int n, m;
 13 int dist[N], getvalue[N], fnode[N];
 14 bool st[N];
 15 int floyd()
 16 {
 17     for (int k = 1; k <= n; k++)
 18         for (int i = 1; i <= n; i++)
 19             for (int j = 1; j <= n; j++)
 20                 gg[i][j] = min(gg[i][j], gg[i][k] + gg[k][j]);
 21     int B0, mind = INF, d[N];
 22     for (int i = 1; i <= n; i++)
 23     {
 24         d[i] = -1;
 25         for (int j = 1; j <= n; j++)
 26             if (gg[i][j] < INF)
 27                 d[i] = max(d[i], gg[i][j]);
 28     }
 29     for (int i = 1; i <= n; i++)
 30     {
 31         if (mind > d[i])
 32         {
 33             mind = d[i];
 34             B0 = i;
 35         }
 36     }
 37     return B0;
 38 }
 39 void Dijkstra()
 40 {
 41     memset(dist, 0x3f, sizeof(dist));
 42     dist[B0] = 0;
 43     getvalue[B0] = 0;
 44     for (int i = 1; i <= n; i++)
 45     {
 46         int mind = INF, maxv = 0, t = -1;//强烈建议用这种写法:y 总的总是会出一些问题:
 47         for (int j = 1; j <= n; j++)
 48         {
 49             if (!st[j])
 50             {
 51                 if (mind > dist[j] || (mind == dist[j] && maxv < getvalue[j]))//维护在能量消耗一样时,选择最大的价值点
 52                 {
 53                     t = j;
 54                     mind = dist[j];
 55                     maxv = getvalue[j];//记得保证更新当前选择的最大价值点
 56                 }
 57             }
 58         }
 59         st[t] = true;
 60         for (int j = 1; j <= n; j++) //是谁更新到这个点的,是在这里;
 61         {
 62             if (!st[j] && g[t][j].power != INF)//注意这里这样写更好
 63             {
 64                 if (dist[j] > dist[t] + g[t][j].power)
 65                 {
 66                     dist[j] = dist[t] + g[t][j].power;
 67                     getvalue[j] = getvalue[t] + g[t][j].value;
 68                     fnode[j] = t;
 69                 }
 70                 else if (dist[j] == dist[t] + g[t][j].power && getvalue[j] < getvalue[t] + g[t][j].value)
 71                 {
 72                     getvalue[j] = getvalue[t] + g[t][j].value;
 73                     fnode[j] = t;
 74                 }
 75             }
 76         }
 77     }
 78 }
 79 int main()
 80 {
 81     memset(gg, 0x3f, sizeof(gg));
 82     scanf("%d%d", &n, &m);
 83     int a, b, p, v;
 84     for (int i = 1; i <= m; i++)
 85     {
 86         scanf("%d%d%d%d", &a, &b, &p, &v);
 87         g[a][b].power = g[b][a].power = p;
 88         g[a][b].value = g[b][a].value = v;
 89         gg[a][b] = gg[b][a] = p;
 90     }
 91     B0 = floyd();
 92     int k, target[N];
 93     scanf("%d", &k);
 94     for (int i = 1; i <= k; i++)
 95         scanf("%d", &target[i]);
 96     Dijkstra();
 97     stack<int> s;
 98     printf("%d\n", B0);
 99     for (int i=1;i<=k;i++)
100     {
101         for (int j=target[i];j!=0;j=fnode[j])
102         {
103             s.push(j);
104         }
105         while (!s.empty())
106         {
107             printf ("%d",s.top());
108             s.pop();
109             if (s.size()>=1) printf ("->");
110         }
111         printf ("\n%d %d",dist[target[i]],getvalue[target[i]]);
112         printf ("\n");
113     }
114     return 0;
115 }

 

 这里还有道好题目:讲到了核心:
 1 Heavy Transportation
 2 描述:
 3 Background
 4 Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now expand business. But he needs a clever man who tells him whether there really is a way from the place his customer has build his giant steel crane to the place where it is needed on which all streets can carry the weight.
 5 Fortunately he already has a plan of the city with all streets and bridges and all the allowed weights.Unfortunately he has no idea how to find the the maximum weight capacity in order to tell his customer how heavy the crane may become. But you surely know.
 6 
 7 Problem
 8 You are given the plan of the city, described by the streets (with weight limits) between the crossings, which are numbered from 1 to n. Your task is to find the maximum weight that can be transported from crossing 1 (Hugo's place) to crossing n (the customer's place). You may assume that there is at least one path. All streets can be travelled in both directions.
 9 输入:
10 The first line contains the number of scenarios (city plans). For each city the number n of street crossings (1 <= n <= 1000) and number m of streets are given on the first line. The following m lines contain triples of integers specifying start and end crossing of the street and the maximum allowed weight, which is positive and not larger than 1000000. There will be at most one street between each pair of crossings.
11 输出:
12 The output for every scenario begins with a line containing "Scenario #i:", where i is the number of the scenario starting at 1. Then print a single line containing the maximum allowed weight that Hugo can transport to the customer. Terminate the output for the scenario with a blank line.
13 样例输入:
14 1
15 3 3
16 1 2 3
17 1 3 4
18 2 3 5
19 复制
20 样例输出:
21 Scenario #1:
22 4
好博客:https://blog.csdn.net/Ratina/article/details/87933057?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-2-87933057-blog-82708228.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-2-87933057-blog-82708228.pc_relevant_default&utm_relevant_index=5
https://blog.csdn.net/STILLxjy/article/details/78169093?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-1-78169093-blog-89299741.pc_relevant_baidufeatures_v7&spm=1001.2101.3001.4242.2&utm_relevant_index=4
posted @ 2022-05-14 18:07  次林梦叶  阅读(40)  评论(0)    收藏  举报