藍橋杯 2014本科C++ B組 地宮取寶 DFS+記憶化搜索

歷屆試題 地宮取寶  ios

時間限制:1.0s   內存限制:256.0MB數組

    

問題描述ide

  X 國王有一個地宮寶庫。是 n x m 個格子的矩陣。每一個格子放一件寶貝。每一個寶貝貼着價值標籤。

  地宮的入口在左上角,出口在右下角。

  小明被帶到地宮的入口,國王要求他只能向右或向下行走。

  走過某個格子時,若是那個格子中的寶貝價值比小明手中任意寶貝價值都大,小明就能夠拿起它(固然,也能夠不拿)。

  當小明走到出口時,若是他手中的寶貝剛好是k件,則這些寶貝就能夠送給小明。

  請你幫小明算一算,在給定的局面下,他有多少種不一樣的行動方案能得到這k件寶貝。spa

輸入格式code

  輸入一行3個整數,用空格分開:n m k (1<=n,m<=50, 1<=k<=12)

  接下來有 n 行數據,每行有 m 個整數 Ci (0<=Ci<=12)表明這個格子上的寶物的價值blog

輸出格式內存

  要求輸出一個整數,表示正好取k個寶貝的行動方案數。該數字可能很大,輸出它對 1000000007 取模的結果。ci

樣例輸入string

2 2 2
1 2
2 1io

樣例輸出

2

樣例輸入

2 3 2
1 2 3
2 1 5

樣例輸出

14

 

話說這個題目意圖仍是蠻明顯的,深搜完後返回全部知足的解的個數,不過這個善意的題目,要想徹底正確仍是學須要在處理時注意不少方面。

首先,先來談第一個問題,寫出其狀態轉移方程,咱們要求的解是從原點手握價值最大的寶物v開始通過不一樣的路徑到終點得到K件寶物的路徑總數,咱們姑且將此狀態記爲

d(1,1,k(初始爲0,還沒拿寶貝),-1(此時手上沒有寶物,值記爲-1))

那麼今後狀態出發,能夠將其轉移爲以下的決策

 

這裏在補充說明用狀態轉移方程能夠方便將原問題分解成若干個與原問題相同的子問題,且規模變小。

第二個問題,若是僅僅這樣的話,必然存在重複計算的問題,爲此必需要採起記憶化搜索的方式,對於已經計算過的結點保存其值,就這條題目而言,必需要用一個四維數組保存由於它的狀態跟位置,個數以及當前最大的寶物價值有關。當重複遍歷這個結點時,直接傳值。

第三個問題,細節決定成敗!!

1.類型用long long穩妥,由於即便MOD了,可是若是兩個數加起來還有可能超int。

2.我本身作的時候沒注意的一個小錯誤,致使最後始終不對的疏忽。我錯誤的把r[MAXN][MAXN][15][15]的初始化爲了0,這絕對不正確,由於有可能以某種方式走的狀態就是無解,就是0,必須將初始值賦爲-1。

3.對於有寶物的初始價值爲-1,比較好的處理方式是,最後存放是第四維的下標後移一位

4.這裏還要注意,k最可能是13,不會超過這個值,因此第三維只要14就夠了

其它的就看代碼吧:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define MAXN 60
 5 #define MOD %1000000007 
 6 using namespace std;
 7 long long r[MAXN][MAXN][15][15];//保存狀態 
 8 long long map[MAXN][MAXN];//初始地圖 
 9 long long m,n,num;
10 long long dfs(long long i,long long j,long long k,long long v)
11 {
12     long long s=0,t;
13     if(r[i][j][k][v+1]!=-1)
14         return r[i][j][k][v+1];
15     if(i==m&&j==n)//到達終點 
16     {
17         if(k==num)
18         {
19             r[m][n][k][v+1]=1;
20             return r[m][n][k][v+1];
21         }
22         else if(k==num-1&&map[m][n]>v)
23         {
24             r[m][n][k][v+1]=1;
25             return r[m][n][k][v+1];
26         }
27         else
28         {
29             r[m][n][k][v+1]=0;
30             return r[m][n][k][v+1];
31         }
32     }
33     else
34     {
35         if(map[i][j]>v)
36         {
37             t=map[i][j];
38             if(i+1<=m)
39             s=(s+dfs(i+1,j,k+1,t)MOD+dfs(i+1,j,k,v)MOD)MOD;
40             if(j+1<=n)
41             s=(s+dfs(i,j+1,k+1,t)MOD+dfs(i,j+1,k,v)MOD)MOD;
42         }
43         else
44         {
45             if(i+1<=m)
46             s=(s+dfs(i+1,j,k,v)MOD)MOD;
47             if(j+1<=n)
48             s=(s+dfs(i,j+1,k,v)MOD)MOD;
49         }
50         r[i][j][k][v+1]=s MOD;
51         return r[i][j][k][v+1];
52     }
53 }
54 int main()
55 {
56 //    freopen("data.in","r",stdin);
57 //    freopen("data.out","w",stdout);
58     memset(r,-1,sizeof(r));
59     long long i,j,p,q;
60     cin>>m>>n>>num;
61     for(i=1;i<=m;i++)
62         for(j=1;j<=n;j++)
63             cin>>map[i][j];
64     dfs(1,1,0,-1);
65     cout<<r[1][1][0][0]<<endl;    
66     return 0;
67 }
View Code
相關文章
相關標籤/搜索