【NOIP2008提高组T3】传纸条-双线程动态规划

来源:互联网 发布:淘宝有发票是正品么 编辑:程序博客网 时间:2024/05/17 08:50

(本人本题完成于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;}

0 0
原创粉丝点击