1. 程式人生 > 實用技巧 >AcWing 1027. 方格取數 dp

AcWing 1027. 方格取數 dp

地址https://www.acwing.com/solution/content/17900/

題目描述
設有 N×N 的方格圖,我們在其中的某些方格中填入正整數,而其它的方格中則放入數字0。
如下圖所示:

某人從圖中的左上角 A 出發,可以向下行走,也可以向右行走,直到到達右下角的 B 點。

在走過的路上,他可以取走方格中的數(取走後的方格中將變為數字0)。

此人從 A 點到 B 點共走了兩次,試找出兩條這樣的路徑,使得取得的數字和為最大。

輸入格式
第一行為一個整數N,表示 N×N 的方格圖。

接下來的每行有三個整數,第一個為行號數,第二個為列號數,第三個為在該行、該列上所放的數。

行和列編號從 
1 開始。 一行“0 0 0”表示結束。 輸出格式 輸出一個整數,表示兩條路徑上取得的最大的和。 資料範圍 N≤10 輸入樣例: 8 2 3 13 2 6 6 3 5 7 4 4 14 5 2 21 5 6 4 6 3 15 7 2 14 0 0 0 輸出樣例: 67

雙dp
由於第一次移動的選擇會影響第二次的移動選擇
那麼考慮兩次同時移動
dp[n][i][j]
n表示移動多少不 i表示第一次移動的橫座標 j表示第二次移動的橫座標
只是的dp意義為 移動n步 第一次移動到n-i,i的位置 第二次移動到n-j,j的位置上
所能取到的最大的數字

val 表示最後所在座標裡的數字
    f[k][x1][x2] 
= max(f[k][x1][x2],f[k-1][x1-1][x2-1]+val); f[k][x1][x2] = max(f[k][x1][x2], f[k - 1][x1 - 1][x2] + val); f[k][x1][x2] = max(f[k][x1][x2], f[k - 1][x1][x2-1] + val); f[k][x1][x2] = max(f[k][x1][x2], f[k - 1][x1][x2] + val);

c++程式碼

// 11235.cpp : 此檔案包含 "main" 函式。程式執行將在此處開始並結束。
//

#include 
<iostream> #include <algorithm> using namespace std; /* 輸入樣例: 8 2 3 13 2 6 6 3 5 7 4 4 14 5 2 21 5 6 4 6 3 15 7 2 14 0 0 0 輸出樣例: 67 */ const int N = 15; int g[N][N]; int n; int f[N + N][N][N]; void solve() { for (int k = 2; k <= (2*n); k++) { for (int x1 = 1; x1 <= n; x1++) { for (int x2 = 1; x2 <= n; x2++) { int y1 = k - x1; int y2 = k - x2; if (x1 >= 1 && x1 <= n && y1 >= 1 && y1 <= n && x2 >= 1 && x2 <= n && y2 >= 1 && y2 <= n) { //================================================================ int val = g[x1][y1]; if (x1 != x2) val += g[x2][y2]; f[k][x1][x2] = max(f[k][x1][x2],f[k-1][x1-1][x2-1]+val); f[k][x1][x2] = max(f[k][x1][x2], f[k - 1][x1 - 1][x2] + val); f[k][x1][x2] = max(f[k][x1][x2], f[k - 1][x1][x2-1] + val); f[k][x1][x2] = max(f[k][x1][x2], f[k - 1][x1][x2] + val); } } } } cout << f[2 * n][n][n]; return ; } int main() { cin >> n; while (1) { int a, b, w; cin >> a >> b >> w; if (a == b && b == w && w == 0) break; g[a][b] = w; } solve(); return 0; }