Acwing_1027_线性DP

题目链接:https://www.acwing.com/problem/content/1029/

解题思路:
首先,这道题目我们基本可以确定是一道DP的题目,但是问题的关键在于怎样去DP;一开始我发现直接先后求两次最大数值,但是发现这样是错误的,然后,我就没有想出来先后分别两次跑路径的解法;但是后面我发现了一个性质:两条路径的起点和终点是一样的,所以这里有一个性质,当我们走到(n, n)的时候,两条路径的列 + 行 这个和一定是相等的,然后对于这两条路劲来说,谁先走是没有影响的,所以我们可以假设两条路径同时走,这样就保证了 行 + 列 的和是一样的;由于有两条路径所以初步的时候可以开辟一个思维举证:
f[i1, j1, i2, j2]后面发现 i1 + j1 == i2 + j2,所以可以优化为 f[k, i1, i2]
但是这里还存在一个问题,就是这两条路径中间可能出现重合的情况,由于我们是dp过来的,所以我们只需要考虑当前情况,这两条路径是否重合,所以我们可以判断:i1 == i2? 来判断此时是否重合。
AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 15;

int n;
int f[maxn * 2][maxn][maxn];
int m[maxn][maxn];

int main(void) {
//	freopen("in.txt", "r", stdin);
	scanf("%d", &n); 
	
	int x, y, z; 
	while(scanf("%d%d%d", &x, &y, &z) && (x || y || z)) m[x][y] = z; 
	
	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 = m[i1][j1];
					if(i1 != i2) t += m[i2][j2];
					
					x = max(x, f[k - 1][i1][i2] + t);
					x = max(x, f[k - 1][i1][i2 - 1] + t);
					x = max(x, f[k- 1][i1- 1][i2] + t);
					x = max(x, f[k - 1][i1 - 1][i2 - 1] + t);
				}
			}
	
	printf("%d\n", f[n * 2][n][n]);
	
	return 0;
}
发布了136 篇原创文章 · 获赞 0 · 访问量 2957

猜你喜欢

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