1. 程式人生 > >問題 1436: [藍橋杯][2014年第五屆真題]地宮取寶

問題 1436: [藍橋杯][2014年第五屆真題]地宮取寶

題目描述

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];
	}

}

這幾個小時花的挺值的,對記憶的理解更進一步了