sincerit 方格取數

2021-09-01 20:52:17 字數 1944 閱讀 4122

設有n*n的方格圖(n<=10),我們將其中的某些方格中填入正整數,而其他的方格中則放入數字0。

某人從圖的左上角的a 點(1,1)出發,可以向下行走,也可以向右走,直到到達右下角的b點(n,n)。在走過的路上,他可以取走方格中的數(取走後的方格中將變為數字0)。

此人從a點到b 點共走兩次試找出2條這樣的路徑,使得取得的數之和為最大

輸入格式

輸入的第一行為乙個整數n(表示n*n的方格圖),接下來的每行有三個整數,前兩個表示位置,第三個數為該位置上所放的數。一行單獨的0表示輸入結束。

輸出格式

只需輸出乙個整數,表示2條路徑上取得的最大的和。

樣例輸入

82 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原先的思路是先走一遍得到乙個最大值,然後把走過的地方數字變為0,再從新走一遍,可是我覺得這樣做沒有依據能得到最大值,然後到網上找別人怎麼做的,發現題目沒那麼簡單。

我原先的思路是得到了區域性最優解,兩個區域性最優解加起來不一定是整體最優解

比如有個人舉得例子:部落格在此:

71 3 2

1 4 3

2 3 3

3 3 3

5 5 4

6 5 4

7 3 2

7 5 4

0 0 0

假如輸入樣例如上,如果用兩次dp的方法,第一次是20,第二次是3,所以最後的權值是23。但是你再看看,我們可以把這個方格的數都取完的,第一次取的權值是17,第二次取得8,這樣就是25了。顯然這是乙個反例,我們上述的想法是錯誤的。

然後正確的做法是:模擬兩個人走一次得到整體最優解

dp[x1][y1][x2][y2] // 表示乙個人走到(x1,y1),乙個人到(x2,y2)的最大值

根據條件到達(x1,y1)的方式有兩種從(x1-1,y1)到達,從(x1, y1-1)到達 這裡跟聰明的kk一樣的走法

這是乙個人到達(x1,y1),還有乙個也跟上面的走法一樣,所以就有

dp[x1 - 1][y1][x2 - 1][y2]:這兩個人都是從左邊走過來的

dp[x1][y1 - 1][x2][y2 - 1]:這兩個人都是從上邊走過來的

dp[x1 - 1][y1][x2][y2 - 1]:第一人從左邊走過來,第二個人從上邊走過來

dp[x1][y1 - 1][x2 - 1][y2]:第一人從上邊走過來,第二個人從左邊走過來

當兩個人走到同乙個點的時候,這個點的值只能加一次,因為另一次走的時候這裡的值為0

if (x1 == x2 && y1 == y2) dp[x1][y1][x2][y2] = mx + map[x1][y1];

並且由可以向下行走,也可以向右走可以發現:兩個人同時走一步,無論兩個人怎麼選擇(每人兩種選擇向下或向右)他們都會在同一條斜線上面 即x1+y1 == x2+y2 (八皇后問題裡的左上斜線)

那麼這裡就可以用來剪枝

#include

#include

#include

#include

#define n 15

using namespace std;

int map[n]

[n];

int dp[n]

[n][n]

[n];

intmain()

for(

int x1 =

1; x1 <= n; x1++

)else}}

}}printf

("%d\n"

, dp[n]

[n][n]

[n])

;return0;

}

方格取數 1

problem description 給你乙個n n的格仔的棋盤,每個格仔裡面有乙個非負數。從中取出若干個數,使得任意的兩個數所在的格仔沒有公共邊,就是說所取的數所在的2個格仔不能相鄰,並且取出的數的和最大。input 包括多個測試例項,每個測試例項包括乙個整數n 和n n個非負數 n 20 ou...

特殊方格取數

特殊方格取數 在n n n 20 的方格棋盤上放置n 個車,某些格仔不能放,求使它們不能互相攻擊的方案總數。第一行,有兩個數 n m n表示方格棋盤大小,m表示不能放的格仔數量 下面有m行,每行兩個整數,為不能放的格仔的位置。只有一行,即得出的方案總數。2 1 1 1 1動態規劃,位運算,排列組合,...

方格取數 2

方格取數 2 時間限制 1 s 空間限制 128000 kb 題目描述 description 給出乙個n n的矩陣,每一格有乙個非負整數aij,aij 1000 現在從 1,1 出發,可以往右或者往下走,最後到達 n,n 每達到一格,把該格仔的數取出來,該格仔的數就變成0,這樣一共走k次,現在要求...