基礎算法題——地宮取寶(深搜、剪枝)

地宮取寶

問題描述
  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;
}

該題具有一般性,比較適合作爲一道深搜模板題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章