题意
给出一个矩阵,起点是 (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+m−2][n][n]
f
[
n
+
m
−
2
]
[
n
]
[
n
]
。
我们可以用数学方法就得到这两条路径的横坐标,然后判断一下就可以进行转移了。
代码
#include<cstdio>
#include<algorithm>
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]);
}