1043 方格取數
時間限制: 1s
空間限制: 128000 KB
題目描述 Description
設有N*N的方格圖(N<=10,我們將其中的某些方格中填入正整數,而其他的方格中則放入數字0。如下圖所示(見樣例):
某人從圖的左上角的A 點出發,可以向下行走,也可以向右走,直到到達右下角的B點。在走過的路上,他可以取走方格中的數(取走后的方格中將變為數字0)。
此人從A點到B 點共走兩次,試找出2條這樣的路徑,使得取得的數之和為最大。

輸入描述 Input Description
輸入的第一行為一個整數N(表示N*N的方格圖),接下來的每行有三個整數,前兩個表示位置,第三個數為該位置上所放的數。一行單獨的0表示輸入結束。
輸出描述 Output Description
只需輸出一個整數,表示2條路徑上取得的最大的和。
樣例輸入 Sample Input
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
樣例輸出 Sample Output
67
數據范圍及提示 Data Size & Hint
如描述
【題解】
這些前些年的NOIP的題目,就看看想下思路就行了,不必要去寫代碼。
這題的動態規划思路十分巧妙。
思路一:
我們設f[i,j,k,l]表示第一條路走到(i,j),第二條路走到(k,l)的路線。
那么狀態轉移方程很好得出:
f[i,j,k,l]=max{f[i-1,j,k-1],f[i-1,j,k,l-1],f[i,j-1,k-1,l],f[i,j-1,k,l-1]}+(i==k&&j==l ? a[i][j] : a[i][j]+a[k][l])
值得注意的是:最后加上這個值的時候要注意如果路徑走到同一點不能重復統計。
時間復雜度:O(n4),空間復雜度O(n4),對於本題n<=10完全足夠。
思路二:
雖然思路一對於本題完全足夠,但是如果n的范圍大些的話,就無法辦到了。
針對思路一,我們發現了問題,有一些狀態是可以合並的,最重要的是:思路一,我們是同時開始走的,那么不必記錄向右、向下的具體路徑,只需要記錄步數,顯然,兩條路的步數是統一的,然后再記錄向下或向右的次數,就能根據這兩者推算出向下或向右的次數。
那么設f[i,j,k]表示走到了第i步,第一條路徑向右走了j步,第二條路徑向右走了k步。
那么f[i,j,k]=max{f[i-1,j,k],f[i-1,j-1,k],f[i-1,j-1,k-1],f[i-1,j,k-1]}+(j==k ? a[i-j+1][i] : a[i-j+1][j]+a[i-k+1][k]);
顯然,我們也要判斷路徑是否走到同一點,所以有后面的那個if( ? : 三目運算符)
時間復雜度:O(2n3),空間復雜度O(2n3),優化了一維。從n的四方優化至n的三方,是一個很大的進步。
至於代碼,只要思路知道了,就無所謂了。
代碼復雜度不高,50行足矣。