1. 程式人生 > 實用技巧 >《Head First 設計模式》:工廠方法模式

《Head First 設計模式》:工廠方法模式

[SHOI2002]滑雪

題目描述

Michael 喜歡滑雪。這並不奇怪,因為滑雪的確很刺激。可是為了獲得速度,滑的區域必須向下傾斜,而且當你滑到坡底,你不得不再次走上坡或者等待升降機來載你。Michael 想知道在一個區域中最長的滑坡。區域由一個二維陣列給出。陣列的每個數字代表點的高度。下面是一個例子:

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

一個人可以從某個點滑向上下左右相鄰四個點之一,當且僅當高度會減小。在上面的例子中,一條可行的滑坡為 \(24-17-16-11\)

(從 \(24\) 開始,在 \(11\) 結束)。當然 \(25-24-23-\ldots…-3-2-1\) 更長。事實上,這是最長的一條。

輸入格式

輸入的第一行為表示區域的二維陣列的行數 \(R\) 和列數 \(C\)。下面是 \(R\) 行,每行有 \(C\) 個數,代表高度(兩個數字之間用 \(1\) 個空格間隔)。

輸出格式

輸出區域中最長滑坡的長度。

輸入輸出樣例

輸入 #1

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

輸出 #1

25

說明/提示

對於\(100\%\)的資料\(1≤R,C≤100\)


分割線
這是一道比較經典的記憶化搜尋,
也是我人生中的第一道記憶化搜尋(我滴媽,可選學會了qwq
剛開始呢,我寫了一個很迷的搜尋,
果不其然,TLE了一個,
神奇的是,WA了兩個???WTF?
然後我又寫了一個搜尋,
只T了一個,(其實我已經寫好了記憶化,只不過把記憶化註釋掉了)
然後去掉註釋,完美的AC了。

#include<cstdio>
#include<algorithm>
using namespace std;
int r,c,a[101][101],ans,dp[101][101];
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
int dfs(int x,int y){
	if(dp[x][y]) return dp[x][y];
	int sum=0;
	for(int i=0;i<4;i++){
		int xx=x+dx[i],yy=y+dy[i];
		if(xx>=1&&xx<=r&&yy>=1&&yy<=c&&a[xx][yy]<a[x][y]){
			sum++;
			dp[x][y]=max(dp[x][y],sum+dfs(xx,yy));
			sum--;
		}
	}
	return dp[x][y]; 
}
int main(){
	scanf("%d%d",&r,&c);
	for(int i=1;i<=r;i++)
		for(int j=1;j<=c;j++)
			scanf("%d",&a[i][j]);
	for(int i=1;i<=r;i++)
		for(int j=1;j<=c;j++){
			dfs(i,j);
			ans=max(ans,dp[i][j]);
		}
	printf("%d",ans+1);
	return 0;
}

其實記憶化不難,
只是我一般都用void寫搜尋(也不知道為啥
但是記憶化得用int,
就弄得我很懵,
然後就沒有然後了,
記憶化還是比較好理解的,
只是在DFS的基礎上加了一個特判,
如果這個點走過,
就直接返回這個點的值。
本蒟蒻撤了qwq