AcWing 1027. 方格取数_DP

题目链接: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题目的切入点和需要解决的关键,然后采用计算思维中的分解思维分别解决这些问题。

发布了136 篇原创文章 · 获赞 0 · 访问量 2996

猜你喜欢

转载自blog.csdn.net/weixin_42596275/article/details/101792085