本文来自:http://blog.csdn.net/hrdv676/article/details/9617667
题目大意:略
解题思路:可以看做是从起点传两次纸条到终点,且两个经过的路线不能有交叉
我们可以用dp[k][i][j]来表示第k步第一个纸条的状态为(i , k+2-i)和第二个纸条的状态(j , k+2-j);
因为i+j=k+2(因为是从(1,1)开始的),所以我们可以只用纸条横坐标i表示它当前所在的状态;
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int map[55][55];
int dp[105][55][55];
int main()
{
int T,n,m,c,t;
int i,j,k;
scanf("%d",&T);
while(T--)
{
memset(dp,0,sizeof(dp));
scanf("%d%d",&m,&n);
for(i = 1; i <= m; i++)
for(j = 1; j <= n; j++)
scanf("%d",&map[i][j]);
c = m + n - 2; //传两次纸条总共走的步数
for(k = 1; k < c; k++)
{
t = k+2 > m ? m : k+2;
for(i = 1; i <= t; i++)
for(j = i+1; j <= t; j++)
{
//由第k-1步四个状态,(右移,下移),(下移,右移),(下移,下移),(右移,右移)可以得到k的状态,取其中中的最大值,然后与当前价值求和
dp[k][i][j] = max(max(dp[k-1][i-1][j],dp[k-1][i][j-1]),max(dp[k-1][i][j],dp[k-1][i-1][j-1])) + map[i][k+2-i] + map[j][k+2-j];
}
}
dp[c][m][m] = max(dp[c-1][m-1][m],dp[c-1][m][m-1]);//最后一步肯定是由上一步(右移,下移)和(下移,右移)得来的
printf("%d\n",dp[c][m][m]);
}
return 0;
}