【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;
}

posted @ 2016-07-18 22:00  Maxwei_wzj  阅读(129)  评论(0编辑  收藏  举报