藍橋杯-地宮取寶

題目描述:

X 國王有一個地宮寶庫。是 n x m 個格子的矩陣。每個格子放一件寶貝。每個寶貝貼着價值標籤。
地宮的入口在左上角,出口在右下角。
小明被帶到地宮的入口,國王要求他只能向右或向下行走。
走過某個格子時,如果那個格子中的寶貝價值比小明手中任意寶貝價值都大,小明就可以拿起它(當然,也可以不拿)。
當小明走到出口時,如果他手中的寶貝恰好是k件,則這些寶貝就可以送給小明。
請你幫小明算一算,在給定的局面下,他有多少種不同的行動方案能獲得這k件寶貝。
【數據格式】
輸入一行3個整數,用空格分開:n m k (1<=n,m<=50, 1<=k<=12)
接下來有 n 行數據,每行有 m 個整數 Ci (0<=Ci<=12)代表這個格子上的寶物的價值
要求輸出一個整數,表示正好取k個寶貝的行動方案數。該數字可能很大,輸出它對 1000000007 取模的結果。
例如,輸入:
2 2 2
1 2
2 1
程序應該輸出:
2
再例如,輸入:
2 3 2
1 2 3
2 1 5
程序應該輸出:
14
資源約定:
峯值內存消耗 < 256M

CPU消耗  < 1000ms

分析:這道題看到的第一反應就是搜索,但是直接搜索不剪枝的話肯定會超時,所以我們採用記憶化搜索。就是搜索和動態規劃相結合的而形成的一種折中的方法。動態規劃會遍歷所有的狀態,而搜索則可以排除一些無效狀態。

下面就是推導狀態轉移方程了,這個題的子問題還是比較明顯的:就是分兩種大的情況,如果寶貝大於手中的價值,那麼可以拿或者不拿,而如果小於則不拿。


另外要注意的地方:①寶物的價值可以爲0,所以一開始搜索的時候,我們要將手中的價值設置爲負數

                              ②有可能某條路徑是不滿題意的,即無解,那麼此時dp就是0,所以我們要初始化dp爲-1,

                                  以便把沒搜索過的情況和搜索過但是無解的情況區分開來

好了,看代碼吧:

import java.util.*;

public class Main {
    static Scanner in = new Scanner(System.in); 
    static int n,m,k,mod = 1000000007;
    static int[][][][] dp = new int[55][55][15][15];
    static int[][] mp = new int[55][55];
    static int dfs(int x,int y,int sum,int val) {
    	if(dp[x][y][sum][val+1]!=-1)//搜索過了,直接返回值
    		return dp[x][y][sum][val+1];
    	if(x==n-1&&y==m-1) {//到達出口
    		 if(sum==k)//寶物數目滿足,可行
    			 return dp[x][y][sum][val+1] = 1;
    		 if(sum==k-1&&mp[x][y]>val)//少一件,但是這個點的寶物可取
    			 return dp[x][y][sum][val+1] = 1;
    		 return  dp[x][y][sum][val+1] = 0;
    	}
    	int t = 0;
    	if(x+1<=n) {//向下走
    		if(mp[x][y]>val) {//可以拿走
    			t = (t+ dfs(x+1,y,sum+1,mp[x][y]))%mod;
    			t%=mod;
    		 }
    		t = (t+ dfs(x+1,y,sum,val))%mod;//不拿走
			t%=mod;
    	}
    	if(y+1<=m) {//向右走
    		if(mp[x][y]>val) {//可以拿走
    			t = (t+ dfs(x,y+1,sum+1,mp[x][y]))%mod;
    			t%=mod;
    		 }
    		t = (t+ dfs(x,y+1,sum,val))%mod;//不拿走
			t%=mod;
    	}
    	return dp[x][y][sum][val+1] = t % mod;
    }
	public static void main(String[] args) {
			n= in.nextInt();
			m = in.nextInt();
			k = in.nextInt();
			int i,j,p,q;
			 for(i = 0;i < 55;i++)
				 for(j = 0;j < 55;j++) 
					 for(p = 0;p < 15;p++)
						 for(q = 0;q < 15;q++)
							 dp[i][j][p][q] = -1;
		 for(i = 0;i < n;i++)
			 for(j = 0;j < m;j++) {
				 mp[i][j] = in.nextInt();
			 }		 
		 System.out.println(dfs(0,0,0,-1));			
	}
}




發佈了262 篇原創文章 · 獲贊 14 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章