ZZULIOJ 1875: 蛤玮的财宝(三维DP)

郑州轻工业大学“玲珑杯ACM程序设计比赛”第二题

 

官方题解:

由于只能往下往右走,所以两条路径的长度是一样的,用dp[l][i][j]表示两个人都走了l步,第一个人在第i行,第二个人在第j行所能得到的最大值,两个人分别往下或往右走一步,有四种转移,如果走到了相同点则权值只加一个.

 

比赛时搞了好久也没搞出来,看了题解后做了一下。AC后对比标准程序,发现比标程简洁些:)

 

标程是对当前状态,计算后面四个状态;而我的代码是从前面四个状态,计算当前状态。

 

#include "algorithm"
#include "iostream"
#include "cstring"
#include "cstdio"
#include "string"
#include "stack"
#include "cmath"
#include "queue"
#include "set"
#include "map"
typedef long long ll;
using namespace std;

const int inf=0x3f3f3f3f;
const int maxn=100+5;

int t,m,n;
int mp[maxn][maxn];
int dp[250][250][250];

int main()
{
    //freopen("in.txt","r",stdin);
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        int sum=0;
        for(int i=1; i<=n; ++i)
        {
            for(int j=1; j<=m; ++j)
            {
                cin>>mp[i][j];
                sum+=mp[i][j];
            }
        }
        if( n<=2 || m<=2 )
        {
            cout<<sum<<endl;
            continue;
        }
        memset(dp,0,sizeof dp);

        dp[0][1][1]=mp[1][1];
        for(int k=1; k<=m+n-2; ++k)
        {
            for(int i1=1; i1<=n ; ++i1)
            {
                for(int i2=1; i2<=n; ++i2)
                {

                    int tmp = dp[k-1][i1][i2];
                    if(i2>1)tmp = max( tmp,dp[k-1][i1][i2-1] );
                    if(i1>1)tmp = max( tmp,dp[k-1][i1-1][i2] );
                    if(i1>1 && i2>1)tmp = max( tmp,dp[k-1][i1-1][i2-1] );

                    //如果两人走到了同一个位置
                    if(i1==i2)
                    {
                        dp[k][i1][i2] += tmp + mp[i1][k+2-i1];
                    }
                    else
                    {
                        dp[k][i1][i2] += tmp + mp[i1][k+2-i1] + mp[i2][k+2-i2];
                    }
                }
            }
        }
        cout<<dp[m+n-2][n][n]<<endl;
    }

}

  

posted @ 2016-04-22 16:01  纸牌  阅读(251)  评论(0编辑  收藏  举报