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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章