NYOJ234-吃土豆(双层DP)

来源:互联网 发布:网络统考报名时间2016 编辑:程序博客网 时间:2024/04/30 02:43

吃土豆

时间限制:1000 ms  |  内存限制:65535 KB
难度:4
描述
Bean-eating is an interesting game, everyone owns an M*N matrix, which is filled with different qualities beans. Meantime, there is only one bean in any 1*1 grid. Now you want to eat the beans and collect the qualities, but everyone must obey by the following rules: if you eat the bean at the coordinate(x, y), you can’t eat the beans anyway at the coordinates listed (if exiting): (x, y-1), (x, y+1), and the both rows whose abscissas are x-1 and x+1.


Now, how much qualities can you eat and then get ?
输入
There are a few cases. In each case, there are two integer M (row number) and N (column number). The next M lines each contain N integers, representing the qualities of the beans. We can make sure that the quality of bean isn't beyond 1000, and 1<=M,N<=500.
输出
For each case, you just output the MAX qualities you can eat and then get.
样例输入
4 611 0 7 5 13 978 4 81 6 22 41 40 9 34 16 1011 22 0 33 39 6
分析:首先,我们可以求出只考虑每一行的情况下,每一行最多能够吃到多少土豆。我们用rowmax[i][j]表示从这一行的开始位置到当前位置(i,j)、并且吃掉当前位置的土豆的情况下能够吃到的土豆最大值。因为要吃掉当前行的第j个位置,则j-1个位置必定是没有被吃过的(否则当前位置是不能吃的),所以,上一个吃土豆的位置可能是j-2或者是j-3。(为什么不是再往前呢?因为如果上一个位置是小于j-3的话,则吃完那个的位置之后最远应该跳到j-2或者j-1的位置,跳到j这个位置的话会使中间有浪费的土豆),所以,计算行最大值时有rowmax[i][j]=max(rowmax[i][j-2],rowmax[i][j-3]) + x,其中x为i,j位置的土豆。
然后考虑行,因为我们吃一行就要隔一行才能吃,所以,我们在吃第i行的时候,一定是吃过i-2或者i-3行之后过来的,如果我们要用dp[i]表示从左上角吃到第i行右下角最多能吃多少的话,则有dp[i]=max(dp[i-2],dp[i-3])+max(rowmax[i][n],rowmax[i][n-1]),因为每一样的最大值必定是吃过最后一个或者倒数第二个之后产生。
参考链接:http://www.cnblogs.com/A-way/archive/2013/05/08/3066236.html
经过分析,代码如下:
#include<stdio.h>#include<string.h>#define N 550int rowmax[N][N],dp[N];int max(int a, int b){    return a>b?a:b;}int main(){    int i,j,n,m,x;      while(scanf("%d %d",&n,&m)!=EOF){        memset(rowmax,0,sizeof(rowmax));        memset(dp,0,sizeof(dp));        for(i=3;i<n+3;i++){            for(j=3;j<m+3;j++){                scanf("%d",&x);                rowmax[i][j]=max(rowmax[i][j-2],rowmax[i][j-3]) + x;            }        }        for(i=3;i<n+3;i++){            dp[i]=max(dp[i-2],dp[i-3])+ max(rowmax[i][m+1],rowmax[i][m+2]);        }        printf("%d\n",max(dp[n+1],dp[n+2]));    }    return 0;}/*4 611 0 7 5 13 978 4 81 6 22 41 40 9 34 16 1011 22 0 33 39 6*/