1. 程式人生 > >P1004 方格取數

P1004 方格取數

body n) 數據 main content tool 輸入輸出格式 ace 推導

P1004 方格取數

題目描述

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

人數字0。如下圖所示(見樣例):

A
 0  0  0  0  0  0  0  0
 0  0 13  0  0  6  0  0
 0  0  0  0  7  0  0  0
 0  0  0 14  0  0  0  0
 0 21  0  0  0  4  0  0
 0  0 15  0  0  0  0  0
 0 14  0  0  0  0  0  0
 0  0  0  0  0  0  0  0
.                       B

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

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

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

輸入輸出格式

輸入格式:

輸入的第一行為一個整數N(表示N*N的方格圖),接下來的每行有三個整數,前兩個

表示位置,第三個數為該位置上所放的數。一行單獨的0表示輸入結束。

輸出格式:

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

輸入輸出樣例

輸入樣例#1:
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
輸出樣例#1:
67

說明

NOIP 2000 提高組第四題

分析:

1. O(n^4)——f[i][j][k][l] 表示分別走到(i,j)和(k,l)的最大和。每次從上一步分別走(向下,向下),(向右,向右),(向右,向下),(向下,向右)的狀態推導就好了。

f[i][j][k][l] = max( f[i-1][j][k-1][l],f[i][j-1][k][l-1],f[i][j-1][k-1][l],f[i-1][j][k][l-1])+a[i][j]+a[k][l]-((i==j&&k==l)?a[k][l]:0);

對於n<=10的數據可以過得去,但在大一點就不行了。

2. O(n^3)——那麽設 f[k,i,j] 表示走到了第 k 步,第一條路徑向右走了 i 步,第二條路徑向右走了 j 步。

那麽f[k,i,j]=max{f[k-1,i,j-1],f[k-1,i-1,j],f[k-1,i-1,j-1],f[k-1,i,j]}+(j==k ? a[k-i+1][i] :a[k-i+1][i]+a[k-j+1][j]); 還有,每一方格的數只能取一次,那麽就要判斷這個點的數取過沒有,也就是判斷兩條路徑是否走到同一點,所以有後面的判斷。 只能說 "方法很奇妙!!!"
 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 
 5 int n;
 6 int mp[12][12];
 7 int f[24][12][12];
 8 
 9 int main()
10 {
11     scanf("%d",&n);
12     for(;;)
13     {
14         int a,b,c;
15         scanf("%d%d%d",&a,&b,&c);
16         if(a==0 && b==0 &&c==0) break;
17         mp[a][b] = c;
18     }
19     for(int k=1;k<=n*2;++k)
20         for(int i=1;i<=k;++i)
21             for(int j=1;j<=k;++j)
22             {
23                 int mx = 0,t;
24                 mx = max(mx,f[k-1][i][j]);
25                 mx = max(mx,f[k-1][i-1][j]);
26                 mx = max(mx,f[k-1][i][j-1]);
27                 mx = max(mx,f[k-1][i-1][j-1]);
28                 if (i==j) t = mp[k-i+1][i];
29                 else t = mp[k-i+1][i]+mp[k-j+1][j];
30                 f[k][i][j] = mx+t;
31             }
32     printf("%d\n",f[n*2][n][n]);
33     return 0;
34 }

P1004 方格取數