挖地雷

题目描述

 在一个地图上有N个地窖(N<=200),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径,并规定路径都是单向的。某人可以从任一处开始挖地雷,然后沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使他能挖到最多的地雷。

输入

   N  {地窖的个数}

  W1,W2,……WN     {每个地窖中的地雷数}

  X1,Y1            {表示从X1可到Y1}

  X2,Y2

……

0 ,0             {表示输入结束}

输出

  K1——K2——……——Kv   {挖地雷的顺序}

  MAX                      {最多挖出的地雷数}

样例输入

6
5 10 20 5 4 5
1 2
1 4
2 4
3 4
4 5
4 6
5 6
0 0

样例输出

3-4-5-6
34


这道题据说是dp,但因为本人dp很菜,于是就写了一个图论的算法。

首先数据范围很和蔼,才<=200.所以我们就可以枚举每一个点作为起始点,然后求出每一次能挖到的最多的地雷数,再尝试更新最终的答案。


具体的操作跟spfa有一点相似,就是如果从当前节点i走到下一个节点j做挖到的地雷数比以前走到j所挖到的地雷数多,就把走到j的路径更新为从i走来的。
同时,因为我们不能确定每一条路那个时候能走到头,所以要一直更新最大值Max。
最后如果从这地i个点出发挖到的地雷数Max>ans的话,就更新ans,同时更新路径。
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<vector>
 8 #include<cctype>
 9 using namespace std;
10 #define enter printf("
")
11 #define space printf(" ")
12 typedef long long ll;
13 const int INF = 0x3f3f3f3f;
14 const int maxn = 2e2 + 5;
15 inline ll read()
16 {
17     ll ans = 0;
18     char ch = getchar(), last = ' ';
19     while(!isdigit(ch)) {last = ch; ch = getchar();}
20     while(isdigit(ch))
21     {
22         ans = ans * 10 + ch - '0'; ch = getchar();    
23     }
24     if(last == '-') ans = -ans;
25     return ans;
26 }
27 inline void write(ll x)
28 {
29     if(x < 0) x = -x, putchar('-');
30     if(x >= 10) write(x / 10);
31     putchar('0' + x % 10);
32 }
33 
34 int n, a[maxn];
35 vector<int> v[maxn];        //存图用         
36 int ans = 0, Path[maxn], pos;        //ans最多地雷数,Path[]记录路径,pos路径长短 
37 
38 int dis[maxn], path[maxn];
39 int spfa(int s, int old)
40 {
41     int Max = a[s], pos = 0;        //注意Max的初值是原点的地雷数,因为可能只有一个点的图 
42     for(int i = 1; i <= n; ++i) dis[i] = path[i] = 0;
43     queue<int> q;
44     q.push(s); dis[s] = a[s];
45     while(!q.empty())
46     {
47         int now = q.front(); q.pop();
48         for(int i = 0; i < (int)v[now].size(); ++i)
49         {
50             if(dis[now] + a[v[now][i]] > dis[v[now][i]])
51             {
52                 dis[v[now][i]] = dis[now] + a[v[now][i]];
53                 path[v[now][i]] = now;                    //记录路径 
54                 if(dis[v[now][i]] > Max) {Max = dis[v[now][i]]; pos = v[now][i];}    //尝试更新Max 
55                 q.push(v[now][i]);
56             }
57         }
58     }
59     if(Max > ans)
60     {
61         ans = Max;
62         int posans = 0;
63         while(path[pos])        //更新路径 
64         {
65             Path[++posans] = pos;
66             pos = path[pos];    
67         }
68         Path[++posans] = s;
69         return posans;        //返回路径的长短 
70     }
71     return old;                //如果更新不成功,那么路径也没有被更新,故返回原来的路径长度 
72 }
73 
74 int main()
75 {
76     n = read();
77     for(int i = 1; i <= n; ++i) a[i] = read();
78     int x = read(), y = read();
79     while(x && y)
80     {
81         v[x].push_back(y);            //vector存图 
82         x = read(); y = read();
83     }
84     for(int i = 1; i <= n; ++i) pos = spfa(i, pos);        
85     for(int i = pos; i > 0; --i) {write(Path[i]); i == 1 ? enter : printf("-");}
86     write(ans); enter;
87     return 0;
88 }
原文地址:https://www.cnblogs.com/mrclr/p/9190724.html