點擊查看:藍橋杯歷年真題 題解目錄
地宮取寶
思路分析:
1. 寫出遞歸框架,中間加上約束條件
2. if(i==m || j==n || count>k) 超過地宮邊界,取出數目>k ,return 0;
3. if (i == m - 1 && j == n - 1) 到達遞歸的出口,再判斷現有的寶貝數目
數目=k,情況數+1; 數目=k-1 並且最後一個寶物大於現有的所有寶物,取走,情況數+1;
4. 其餘未達到k的情況 不做處理,下次循環 將超出地宮邊界,return 0;
5. 對遞歸體: if(current>max) 則可以取出(count+1) 再向右或向下遞歸
也可以不取出,再向右和向下遞歸
if(current<=max) 只能不取出,再向右和向下遞歸
6. 對每步得到的 ans 對1000000007取模
7. 對記憶型遞歸而言: 在遞歸結尾 記錄狀態值
在遞歸開頭,判斷狀態值是否被記錄,若被記錄直接 return 狀態值,未被記錄 執行遞歸。
package java_2014_B;
import java.util.Scanner;
public class Main009_地宮取寶 {
static int m,n,k;
static int[][] a;
static int [][][][]f = new int[51][51][14][14];
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
m = in.nextInt();
n = in.nextInt();
k = in.nextInt();
a = new int[m][n];
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
a[i][j]=in.nextInt(); // 初始化記憶型遞歸的數組
for(int i=0;i<51;i++)
for(int j=0;j<51;j++)
for(int l=0;l<14;l++)
for(int o=0;o<14;o++)
f[i][j][l][o]=-1;
long ans = dfs(0,0,-1,0);
System.out.println(ans);
}
private static long dfs(int i, int j, int max, int count) {
if(f[i][j][max+1][count] != -1) return f[i][j][max+1][count];
if(i==m || j==n || count>k) {
return 0;
}
int cur=a[i][j],ans=0;
if (i == m - 1 && j == n - 1) {
if (count == k || (count == k - 1 && cur > max))
return 1;
return 0;
}
if(cur>max) {
ans+=dfs(i, j+1, cur, count+1); // 取出當前的寶藏,向右走
ans%=1000000007;
ans+=dfs(i+1, j, cur, count+1); // 取出當前的寶藏,向下走
ans%=1000000007;
}
ans+=dfs(i, j+1, max, count); // 不取當前寶藏,向右走
ans%=1000000007;
ans+=dfs(i+1, j, max, count); // 不取當前寶藏,向下走
ans%=1000000007;
f[i][j][max+1][count]=ans%1000000007;
return ans;
}
}