HDU 2845 Beans

Beans

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1819    Accepted Submission(s): 921

Problem Description
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 ?
 
Input
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<=200000.
 
Output
For each case, you just output the MAX qualities you can eat and then get.
 
Sample Input
4 6
11 0 7 5 13 9
78 4 81 6 22 4
1 40 9 34 16 10
11 22 0 33 39 6
 
Sample Output
242
 
Source
 
Recommend
gaojie
 
 

把二维按行列分解然后dp

 

dp[i][0] 表示不取第i个能到的最大值

 

所以dp[i][0] = Max(dp[i-1][0],dp[i-1][1]);

 

dp[i][1] 表示取第i个能到的最大值

 

所以dp[i][1] = dp[i-1][0]+value[i];

 

row[i]记录下每一行的最优情况,然后再按照上面的方法进行dp

 

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const int N=200010;

int m,n;
int dp[N][2],val[N],row[N];

int main(){

    //freopen("input.txt","r",stdin);

    while(~scanf("%d%d",&m,&n)){
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&val[j]);
                dp[j][0]=max(dp[j-1][0],dp[j-1][1]);
                dp[j][1]=dp[j-1][0]+val[j];
            }
            row[i]=max(dp[n][0],dp[n][1]);
        }
        for(int i=1;i<=m;i++){
            dp[i][0]=max(dp[i-1][0],dp[i-1][1]);
            dp[i][1]=dp[i-1][0]+row[i];
        }
        printf("%d\n",max(dp[m][0],dp[m][1]));
    }
    return 0;
}
 
 
挺有意思的题。 吃了一个豆豆后,上下2行的豆豆都不能吃。这个很关键,突破口就在这。那我们只要考虑一行最多能吃多少,然后得到每行最多能吃多少。这样得到的m个数排成一行,就很之前求一行的一样了,就是如果前面一个吃了,后面的就不能再吃,也就是不能相邻。这道题和树形DP那道 不能和有直接关系的上级一起出席聚会的题很像。 所以对于一行还说,状态表示dp[i][j],j要么取0,要么取1,表示第i个数取了没。
状态转移就是dp[i][0]=max(dp[i-1][0],dp[i-1][1])   dp[i][1]=dp[i-1][0]+val[i]
这道题只给出了M*N,不可能用2个数定一个位置。所以就用了dp[i][j],1<=i<=M*N j=0,1
得到每行的最大值后(max(dp[i][0],dp[i][1]),i=n*k),再对这些最大值dp,方法一样,状态的第一个参数也是MAX,因为N可能为1.
 
 
#include<stdio.h>
#include<string.h>

const int maxn=200010;

int dp_row[maxn][2];
int dp_col[maxn][2];

int max(int a,int b){
    return a>b?a:b;
}

int main(){

    //freopen("input.txt","r",stdin);

    int m,n;
    while(scanf("%d%d",&m,&n)!=EOF){
        memset(dp_row,0,sizeof(dp_row));
        memset(dp_col,0,sizeof(dp_col));
        int tmp;
        for(int i=1;i<=m*n;i++){
            scanf("%d",&tmp);
            if(i%n==1){
                dp_row[i][0]=0;
                dp_row[i][1]=tmp;
            }else{
                dp_row[i][0]=max(dp_row[i-1][0],dp_row[i-1][1]);
                dp_row[i][1]=dp_row[i-1][0]+tmp;
            }
        }
        for(int i=1;i<=m;i++){
            dp_col[i][0]=max(dp_col[i-1][0],dp_col[i-1][1]);
            dp_col[i][1]=dp_col[i-1][0]+max(dp_row[i*n][0],dp_row[i*n][1]);
        }
        printf("%d\n",max(dp_col[m][0],dp_col[m][1]));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jackge/p/2979861.html