• 题解:2018级算法第六次上机 C6-危机合约


    题目描述

    样例:

    实现解释:

    没想到你也是个刀客塔之二维DP

    知识点:

    动态规划,多条流水线调度?可以看做一种流水线调度

    坑点:

    输入内容的调整(*的特殊判定),开头结尾的调整策略

    从题意可知,要做的就是从起始点移动到蓝点,并且在过程中会有一个值的记录,这就可以和一些基础题目联系起来:捡金币问题,流水线问题等等。

    不过注意在使用板子时需要注意值的调度策略:对无法过去的地点,可将敌人攻击值设为99999,即无限,从而在进行动态规划时也可直接参与计算。借助这一攻击无限化的想法,对第一列和最后一列也需要进行处理:无法从开始点直接进入的第一列的值和无法在最后一列到达结束点,同样是到达无意义(无法上下移动),因此设为无穷。

    调整之后便可直接借助dp进行,假设dp数组为dp[i][j]:到达第ij列时的最小受损值。则很容易可得到状态转移方程:dp[i][j] = min(dp[i][j-1],dp[i-1][j-1],dp[i+1][j-1]) + a[i][j];

    基于方程递归进行即可,注意dp的初始化(第一列),这里由于是参考多条流水线进行的编写,因此应该会很熟悉。

    完整代码:

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define NO 99999
    int a[110][110];
    int main()
    {
        ios::sync_with_stdio(false);
        int n,m;
        cin >> n >> m;
        int a[n][m];
        int dp[n][m];
        int h,from,to;
        char temp;
        cin >> h >> from >> to;
        for(int i = 0;i<n;i++)
        {
            for(int j = 1;j<=m;j++)
            {
                cin >> temp;//便于比较是否可通行 
                if(temp == '*') a[i][j] = NO;//不可通行则设为一定死的值
                else a[i][j] = temp-'0';//否则存储数字 
            }
        }
        from -= 1;
        to -= 1;
        //这里是为了和脚标配合进行的处理 
        for(int i = 0;i<n;i++)
        {
            //第一列中开局不能到达的,最后一列中不能到结束点的
            //相当于不可达,设为大值 
            if(abs(from-i) > 1) a[i][1] = NO;
            if(abs(to-i) > 1) a[i][m] = NO;
        }
        for(int i = 0;i<n;i++)
        {
            //象征性的初始化,第一列 
            dp[i][1] = a[i][1];
        }
        int tempf;//存储临时的掉血数 
        for(int i = 2;i<=m;i++)
        {
            for(int j = 0;j<n;j++)
            {
                //向右走 
                tempf = dp[j][i-1]+a[j][i];
                //判断右上和右下 
                for(int k = -1;k<=1;k+=2)
                {
                    //越界则跳过 
                    if(j+k<0||j+k>n-1) continue;
                    if(tempf > dp[j+k][i-1]+a[j][i])
                    {
                        tempf = dp[j+k][i-1]+a[j][i];
                    }
                }
                dp[j][i] = tempf;
            }
        }
        //获取最小值设为最大值 
        tempf = NO;
        for(int k = -1;k<=1;k++)
        {
            if(to+k<0||to+k>n-1) continue;//越界跳过 
            if(dp[to+k][m] > NO) continue;//有不可达的点,跳过 
            if(dp[to+k][m] < tempf) tempf = dp[to+k][m];//最小值 
        }
        //判断最小掉血数和hp的关系 
        if(tempf-h > 0) cout << "doctor win
    ";
        else cout << h-tempf << '
    ';
        return 0;
    }
    View Code
  • 相关阅读:
    pycharm上运行django服务器端、以及创建app方法
    Python实现淘宝秒杀聚划算自动提醒源码
    Python版:Selenium2.0之WebDriver学习总结_实例1
    windows上使用pip下载东西时报编码错误问题解决方法
    模块购物商城和ATM机代码:
    Python网页信息采集:使用PhantomJS采集淘宝天猫商品内容
    android用户界面之ProgressBar教程实例汇总
    推荐12个亲测Android开发源码(包括应用、游戏、效果等等)
    Android开发各种demo集合
    Android Service
  • 原文地址:https://www.cnblogs.com/doUlikewyx/p/11947800.html
Copyright © 2020-2023  润新知