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