UESTC 2016 Summer Training #2 Div.2(未完待续)

题目来源:SPOJ AMR11、UVALive 5983-5992

A
题意:给出一个n*m的图,从左上角出发,去右下角,只能向下或者向右走,每个格子有权值,问如何安排你在左上角时的权值,使得到达右下角时权值大于1。

做法:一开始想到的就是简单的直接DP,却发现有些问题,因为在过程中可能会出现不合法的情况,会影响到最后的情况,可是却不容易想清楚最后是因为什么导致答案错误。
因此最后的做法大致有两种:
1)用二分枚举答案,然后正向DP,找到符合条件的最小的答案。
2)逆向DP,假设最后走到终点是体力为1,在逆推的过程中,记住一旦出现小于1的体力值,就要将其改为1,最后得到的DP矩阵中最小的数一定只能是1

下面代码是第二种做法。第一种做法网上也很多,可以自行去找。

#include <bits/stdc++.h>

#define INF 0x3f3f3f3f
#define eps 1e-6
typedef long long LL;
const double pi = acos(-1.0);
const long long mod = 1e9 + 7;
using namespace std;

int R,C,T;
int S[505][505];
int dp[505][505];

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        memset(S,0,sizeof(S));
        scanf("%d %d",&R,&C);
        for(int i = 1;i <= R;i++)
            for(int j = 1;j <= C;j++)
                scanf("%d",&S[i][j]);

        memset(dp,0,sizeof(dp));
        dp[R][C] = 1;
        for(int i = R - 1;i > 0;i--)
            dp[i][C] = max(dp[i + 1][C] - S[i][C],1);
        for(int j = C - 1;j > 0;j--)
            dp[R][j] = max(dp[R][j + 1] - S[R][j],1);
        for(int i = R - 1;i > 0;i--)
            for(int j = C - 1;j > 0;j--)
                dp[i][j] = max(min(dp[i + 1][j],dp[i][j + 1]) - S[i][j],1);
        printf("%d\n",dp[1][1]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值