【动态规划】Contest Hunter_5103 传纸条

题意

给出一个矩阵,起点是 (1,1) ( 1 , 1 ) ,终点是 (n,m) ( n , m ) ,现在有两条路径从起点走到终点,经过一个格子就把它上面的价值加起来,两条路径如果有重复的部分,那加上的价值就按一个算,求出最大的价值。

思路

这道题可以用四维的动态规划,但是由于可以利用数学方法降到三维,所以打三维的更好。
f[i][x1][x2] f [ i ] [ x 1 ] [ x 2 ] 表示路径长度为i,第一条路在第 x1 x 1 行,第二条路在 x2 x 2 行时的最大价值,那答案就为
f[n+m2][n][n] f [ n + m − 2 ] [ n ] [ n ]
我们可以用数学方法就得到这两条路径的横坐标,然后判断一下就可以进行转移了。

代码

#include
#include
using namespace std;
int f[299][101][101],a[101][101],n,m,y_1,y_2;
int main() {
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
    f[0][1][1]=a[1][1];
    for (int i=0;i<=n+m-2;i++) {
        for (int x_1=1;x_1<=n;x_1++)
            for (int x_2=1;x_2<=n;x_2++) {
                y_1=i+2-x_1;
                y_2=i+2-x_2;
                if (x_1==x_2) f[i+1][x_1][x_2]=max(f[i+1][x_1][x_2],f[i][x_1][x_2]+a[x_1][y_1+1]);
                else f[i+1][x_1][x_2]=max(f[i+1][x_1][x_2],f[i][x_1][x_2]+a[x_1][y_1+1]+a[x_2][y_2+1]);//两个都往右走
                if (x_1+1==x_2) f[i+1][x_1+1][x_2]=max(f[i+1][x_1+1][x_2],f[i][x_1][x_2]+a[x_1+1][y_1]);
                else f[i+1][x_1+1][x_2]=max(f[i+1][x_1+1][x_2],f[i][x_1][x_2]+a[x_1+1][y_1]+a[x_2][y_2+1]);//一个往下走,一个往右走
                if (x_1==x_2+1) f[i+1][x_1][x_2+1]=max(f[i+1][x_1][x_2+1],f[i][x_1][x_2]+a[x_2+1][y_2]);
                else f[i+1][x_1][x_2+1]=max(f[i+1][x_1][x_2+1],f[i][x_1][x_2]+a[x_2+1][y_2]+a[x_1][y_1+1]);//一个往右走,一个往下走
                if (x_1+1==x_2+1) f[i+1][x_1+1][x_2+1]=max(f[i+1][x_1+1][x_2+1],f[i][x_1][x_2]+a[x_1+1][y_1]);
                else f[i+1][x_1+1][x_2+1]=max(f[i+1][x_1+1][x_2+1],f[i][x_1][x_2]+a[x_1+1][y_1]+a[x_2+1][y_2]);//都往右走
            }
    }
    printf("%d",f[n+m-2][n][n]);
}

你可能感兴趣的:(动态规划)