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

来源:互联网 发布:数据库开发与管理 编辑:程序博客网 时间:2024/05/18 17:39

题目来源: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-6typedef 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;}
0 0
原创粉丝点击