【NOIP2008提高组T3】传纸条-双线程动态规划
(本人本题完成于2016-7-18)
题目大意:一个m*n的矩阵,要从(1,1)开始寻找两条不同路径到(m,n),使经过的点权之和最大,输出这个最大值。
分析:双线程dp,f[i][j]表示当一条路线(以下称为A路线)走到第i行,另一条路线(以下称为B路线)走到第j行时,已得到的点权之和最大值,不难得出f[i][j]可由四种情况推出:f[i][j](前一步A路线走到i行,B路线走到j行),f[i-1][j](前一步A路线走到i-1行,B路线走到j行),f[i][j-1](前一步A路线走到i行,B路线走到j-1行),f[i-1][j-1](前一步A路线走到i-1行,B路线走到j-1行),设当前所走步数为k,可以得出A路线走到(i,k+2-i),B路线走到(j,k+2-j),则状态转移方程为:
f[i][j]=max(f[i][j],f[i-1][j],f[i][j-1],f[i-1][j-1])+(i,k+2-i)点权+(j,k+2-j)点权
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
long m,n,f[51][51]={0},v[51][51]={0}; //m为行数,n为列数,v[i][j]为(i,j)的点权
int main()
{
scanf("%ld %ld",&m,&n);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
scanf("%ld",&v[i][j]);
for(int k=0;k<=n+m-2;k++) //k枚举步数
for(int i=m;i>=1;i--)
for(int j=m;j>=1;j--) //注意i,j两重循环顺序,保证结果正确性
{
if (k==n+m-2&&i==m&&j==m) //最后的结果特殊判断
f[i][j]=max(max(f[i][j],f[i-1][j-1]),max(f[i-1][j],f[i][j-1]))+v[i][k+2-i]+v[j][k+2-j];
else if (i!=j&&k+2-i>=1&&k+2-j>=1) //条件i!=j是为防止两路线走到同一个点,其余两个条件是为防止坐标超越边界
f[i][j]=max(max(f[i][j],f[i-1][j-1]),max(f[i-1][j],f[i][j-1]))+v[i][k+2-i]+v[j][k+2-j];
}
printf("%ld",f[m][m]);
return 0;
}