什麼情況下,使用記憶化搜索比動態規劃更加方便???

動態規劃是自底向上的,先處理子問題,然後再處理更大的問題。這樣就需要知道子問題和更大的問題之間的聯繫。我們能夠確定出子問題並且能夠正確的求解它,從而從子問題推出要解決的問題的解。

但是,如果當我們比較難確定出子問題是哪一個,比較困難的求出子問題的答案時,可以使用記憶化搜索

以洛谷上的滑雪題爲例

對於這道題,我們沒辦法馬上求得到達某個點的最長長度

因此我們需要使用遞歸方法,並且使用記憶化搜索來進行優化

思路

使用遞歸計算出,到x,y點的最長滑坡長度 

遍歷點(x,y)的上下左右四個點,如果一個點的值是小於點(x,y),說明這個點可以滑到點(x,y)

答案爲,四個點中最長滑坡長度的最大值+1

res = max(res,getMax(newx,newy)+1);

使用循環更新數組的值,直到數組所有的值都被更新,找到數組中最大的那個值

代碼

#include <iostream>
#include <vector>
using namespace std;
/**
輸入 
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
輸出 
25
*/

int memo[105][105];
int quyu[105][105];
int R,C;
bool inArea(int x, int y )
{
	return x>=1 && y>=1 && x<=R && y<=C;
}
//到x,y點的最長滑坡長度 
int d[4][2] ={0,-1,1,0,-1,0,0,1};
int getMax(int x,int y)
{
	//上下左右四個點中可達該點的數
	if(memo[x][y]!=-1) return memo[x][y];
	int res = 1; 
	for(int i=0; i<4; i++)
	{
		int newx = x+d[i][0];
		int newy = y+d[i][1];
		if(inArea(newx,newy) && quyu[x][y]>quyu[newx][newy]) 
		{
			res = max(res,getMax(newx,newy)+1);
		}
	}
	memo[x][y] = res;
	return res;	 
}
int main()
{
	cin>>R>>C;
	for(int i=1; i<=R; i++)
	{
		for(int j=1; j<=C; j++)
			cin>>quyu[i][j];
	}
	int res = 0; 
	for(int i=0; i<105; i++)
		for(int j=0; j<105; j++)
			memo[i][j]=-1;
			
	for(int i=1; i<=R; i++)
	{
		for(int j=1; j<=C; j++)
		{
			if(memo[i][j]==-1)
				res=max(res,getMax(i,j));
			else
				res=max(res,memo[i][j]);
		}
	}
	cout<<res<<endl;
	
	return 0;
} 

 

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