地宮取寶
問題描述
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
這道題與一般的dfs題目大同小異,做題基本思路:遞歸+剪枝
細節問題:
①拿寶物條件:格子中的寶貝價值比小明手中任意寶貝價值都大才能拿。
②如何設置cache數組:與描述dfs狀態的變量相匹配,並將元素全部置爲-1。寶物價值:0<=Ci<=12,若cache數組元素全部置爲0的話,則會遺漏取價值爲0的寶物的路徑。
③如何設置沒拿寶物時Max的值:初始化Max=-1。寶物價值:0<=Ci<=12,一開始沒拿寶物不能有Max=0,否則會遺漏取價值爲0的寶物的路徑。(注意:Max等於負數cache數組的下標不能爲負數,要計作Max+1,同時cache數組記錄Max的下標上限要加1,因爲當Max=12時,Max+1=13)
#include<bits/stdc++.h>
using namespace std;
int bk[55][55], n, m, k;
int cache[55][55][14][13]; //記憶路徑,防止重複,剪枝
const long long Mod=1e9+7;
long long dfs(int n1, int m1, int Max, int k1)
{
if(cache[n1][m1][Max+1][k1]!=-1) //使用Max+1避免Max=-1對cache數組下標造成影響
return cache[n1][m1][Max+1][k1];
long long ans=0; //未走過的路徑創建一個ans變量
if(n1==n||m1==m||k1>k) //出界,直接退出
return 0;
if((n1==n-1&&m1==m-1&&k1==k)||(k1==k-1&&n1==n-1&&m1==m-1&&bk[n1][m1]>Max))
{
ans++;
return ans;
}
//不拿
ans+=dfs(n1+1, m1, Max, k1);
ans+=dfs(n1, m1+1, Max, k1);
//拿
if(bk[n1][m1]>Max)
{
ans+=dfs(n1+1, m1, bk[n1][m1], k1+1);
ans+=dfs(n1, m1+1, bk[n1][m1], k1+1);
}
cache[n1][m1][Max+1][k1]=ans%Mod;
return ans%Mod;
}
int main()
{
cin>>n>>m>>k;
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
cin>>bk[i][j];
memset(&cache, -1, sizeof(cache));
//Max初始化爲-1
cout<<dfs(0, 0, -1, 0);
return 0;
}
該題具有一般性,比較適合作爲一道深搜模板題。