郑州轻工业大学“玲珑杯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;
}
}