挖地雷的算法

O: 【基础】挖地雷的算法

题目描述

在一个地图上有n个地窖(n<=200),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径,并规定路径都是单向的,且保证都是小序号地窖指向大序号地窖,也不存在可以从一个地窖出发经过若干地窖后又回到原来地窖的路径。某人可以从任一处开始挖地雷,然后沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使他能挖到最多的地雷。

如下图所示:圆圈内的1 2 3 4 5 6,代表6个地窖的编号,地窖编号旁边的数字代表这个地窖地雷的数量!

输入

第一行:地窖的个数;
第二行为依次每个地窖地雷的个数;
下面若干行:
xi yi //表示从xi可到yi,xi<yi。
最后一行为"0 0"表示结束。

输出

第一行输出挖地雷的地窖编号的顺序:k1-k2-…-kv

第二行输出一个整数,代表最多能挖到的地雷的数量

样例输入

65 10 20 5 4 51 21 42 43 44 54 65 60 0

样例输出

3-4-5-634

分析

如果从小节点搜索的话太多了,一次考虑从最大节点开始,记录dp[i]为从i节点开始能够得到的地雷数量,那么dp[i] = v[i] + max(dp[j]),dp[j]是所有和i节点有关系的i之后的节点,怎么打印路径,可以考虑记录第i次选择的后继节点为path[i]

代码

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    //
    // freopen("E:/Code/C++/untitled1/input.txt","r",stdin);
    // freopen("output.txt","w",stdout);


    int n;
    cin >> n;
    int v[210];int dp[210],paths[210];//paths记录每个节点选择的下一个节点,
    bool vis[210][210];//邻接矩阵,记录路径
    mem(vis);
    mem(v);
    mem(paths);
    f(i,1,n+1)//读入
    {
        cin >> v[i];
    }
    int x,y;
    while (cin >> x >> y && x && y)
        vis[x][y] = true;


    dp[n] = v[n];//边界节点的地雷数量
    int index = 0 ,count = 0;//index记录最大下一个节点,count记录最大下一个节点的值
    for(int i = n-1; i>= 1;i--)//由于是从小指向大的,所以最大节点肯定没有指出的路径
    {
        count = 0;
        for(int j = i + 1;j <= n;++j)
        {
            if(vis[i][j] && dp[j] > count)
            {
                index = j;
                count = dp[j];
            }
            dp[i] = v[i] + count;//状态转移
            paths[i] = index;//记录路径
        }
    }
    index = 1;
    for(int i = 2;i <= n;++i)
        if(dp[i] > dp[index]) index = i;//找最大结果
    int asn = dp[index];
    while (index)
    {
        cout << index;
        index = paths[index];
        if(index) cout << '-';
    }
    cout << '\n';
    cout << asn << '\n';


}

posted @   bakul  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示