問題 1436: [藍橋杯][2014年第五屆真題]地宮取寶
阿新 • • 發佈:2018-12-19
題目描述
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 3 2 1 2 3 2 1 5
樣例輸出
14
WA和超時了一箇中午,總結一下記憶化搜尋,其實思路已經到位了,就是學到了很多邊界的處理,先從開空間說起,有多少個引數就開多少維空間,memo陣列的初始值設為-1,而不是0,不然記憶搜尋會退化導致超時,另外一個要注意的就是陣列的值範圍為0-12,所以你穿入的max不能為0,應該為-1,但是開的空間下標總不能為負數把,所以可以讓所有數組裡面的值+1就等價於max改為-1了。
import java.util.Scanner; public class 地宮取寶 { static int n,m,k; static int[][] a = new int[55][55]; static int[][][][] memo = new int[55][55][13][13]; static int mod = 1000000007; public static void main(String[] args) { Scanner in = new Scanner(System.in); n = in.nextInt(); m = in.nextInt(); k = in.nextInt(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j] = 1+in.nextInt(); for(int i=0;i<=54;i++) for(int j=0;j<=54;j++) for(int ii=0;ii<=12;ii++) for(int jj=0;jj<=12;jj++) memo[i][j][ii][jj]=-1; System.out.println(dfs(1,1,0,0)); } static int dfs(int x,int y,int t,int max) { if(memo[x][y][t][max]!=-1) return memo[x][y][t][max]; memo[x][y][t][max]=0; if(x==n && y==m && t==k) memo[x][y][t][max] = 1; if(a[x][y]>max && t<k) { memo[x][y][t][max] += dfs(x,y,t+1,a[x][y]); memo[x][y][t][max]%=mod; } if(x<n) { memo[x][y][t][max] += dfs(x+1,y,t,max); memo[x][y][t][max]%=mod; } if(y<m) { memo[x][y][t][max] += dfs(x,y+1,t,max); memo[x][y][t][max]%=mod; } return memo[x][y][t][max]; } }
這幾個小時花的挺值的,對記憶的理解更進一步了