题目链接:https://www.acwing.com/problem/content/1029/
解题过程:
刚开始拿道这道题目的时候,我是直接跑2次DP,后来发现答案似乎不太对,想了一下,这样是由问题的,我们不能保证直接分别跑2次得到的答案就是最优解;然后,我第二次是想要开一个三维数组,以此来记录2次的路线,但是始终不能退出状态转移方程;后来想了好久还是没有思路,最后没办法了,只好看题解。
解题思路:
代码:
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 15;
int n;
int w[maxn][maxn];
int f[maxn * 2][maxn][maxn];
int main(void) {
scanf("%d", &n);
int a, b, c;
while(scanf("%d%d%d", &a, &b, &c) && (a || b || c)) w[a][b] = c;
for(int k = 2; k <= 2 * n; k ++)
for(int i1 = 1; i1 <= n; i1 ++)
for(int i2 = 1; i2 <= n; i2 ++) {
int j1 = k - i1, j2 = k - i2;
if(j1 >= 1 && j1 <= n && j2 >= 1 && j2 <= n) {
int &x = f[k][i1][i2];
int t = w[i1][j1];
if(i1 != i2) t += w[i2][j2];
x = max(x, f[k - 1][i1][i2] + t);
x = max(x, f[k - 1][i1 - 1][i2] + t);
x = max(x, f[k - 1][i1][i2 - 1] + t);
x = max(x, f[k - 1][i1 - 1][i2 - 1] + t);
}
}
printf("%d\n", f[n * 2][n][n]);
return 0;
}
总结:
我发现这道题目的切入点在于去使用怎样的方法去刚好记录2条路径的转移,而且由于2条路径的某些地方可能重合,我们就还需要考虑到重合的点;
对于第一个疑问:我们本质上是直接 开4数组
对于第二个疑问:我们可以同时对2条路径进行转移,即2条路径的时间是一样的,所以有:i1 + j1 == i2 + j2 == k
所以我们在做DP的时候我们需要从题目中去找到(总结出)这个DP题目的切入点和需要解决的关键,然后采用计算思维中的分解思维分别解决这些问题。