• 挖地雷


    题目描述

     在一个地图上有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 }
  • 相关阅读:
    z-index优先级小结
    如何消除img间的默认间隙
    text-align和vertical-align
    HTTP
    HTTP
    HTTP
    HTTP
    ES6标准入门
    ES6标准入门
    ES6标准入门
  • 原文地址:https://www.cnblogs.com/mrclr/p/9190724.html
Copyright © 2020-2023  润新知