---
# System prepended metadata

title: UVA 10825 - Longest Run on a Snowboard

---

# UVA 10825 - Longest Run on a Snowboard

*算法： Greedy、BruteForce、DP*


### 題目：
給你一個$R \times C$的矩陣每個點代表一個高度 $H_i$ ，找到一條高度嚴格遞減的最長路徑，路徑只能上下左右走且不能走出矩陣外。

[原題目](https://onlinejudge.org/index.php?option=onlinejudge&Itemid=8&page=show_problem&problem=1226)

### 輸入：
$T$ 筆測資
每筆測資的第一行有一個不含空格的字串，$R,C$ 代表行、列數，以空格隔開
接著R行有C個整數$Hi$ 

$N \leq 15$
$R,C \leq 100$
$0 \leq H_i \leq 100$

### 輸出：
一開始輸入的字串+": "+最長路徑長


### 解法：

*測資很小直接枚舉也行，~~但因為我DP很爛所以這裡用DP解。~~*

上下左右走，感覺能BFS但其實用DFS會更好，因為BFS比較適合求最短路

DP( i , j ) 代表( i , j )這個點能走的最長路徑長。


可得
$DP( i , j ) = max( DP( i , j ) , 下一個點的最長路徑長+1 )$

這樣能順便處理下一個點的最長路徑長，不用再跑一次。

處理邊界的部分，矩陣外面的高度全都INF，
還沒處理過的點設成-1，處理過一定大於等於1(最長路徑長最短為1)



#### 程式碼(Accepted,C++11,Runtime: 0.000)：
```cpp
#pragma GCC optimize("Ofast")
#pragma loop_opt(on)
#include<bits/stdc++.h>
//#include<bits/extc++.h>
using namespace std;
template<class T> long long Mod(T a,T b){return ((a%b)+b)%b;}
#define endl '\n'
#define ll long long
#define IO ios_base::sync_with_stdio(0); cin.tie(0);
#define GETOUT cout.tie(0);
#define cendl cout << endl;
#define fr(bob,n,l) for(int bob=(n);bob<(l);++bob)
#define fra(ns,a) for(auto (ns):a)
#define frc(bot,ns,l) for(int bot=(ns);bot<=(l);++bot)
#define frx(i,ns,l) for(int i=(ns);i<(l);++i)
#define mem(arr,initn) memset(arr,initn,sizeof(arr))
#define ALL(va) (va).begin(),(va).end()
#define ALLa(arr) (arr),(arr)+sizeof((arr))/sizeof((arr)[0])
#define printv(va) {fr(i,0,size((va))){cout<<(va)[i]<< ' ';}cendl;}
#define printa(va) {fr(i,0,sizeof((va))/sizeof((va)[0])){cout << (va)[i] << ' ';}cendl;}
#define getpos(va,v) lower_bound((v).begin(),(v).end(),(va)) - (v).begin()
#define arrpos(i,va) distance((va),find(ALLa((va)),i))
#define pb emplace_back
typedef pair<int,int> pii;
#define fi first
#define se second
#define setu(x,y,v) set_union(x.begin(),x.end(),y.begin(),y.end(),back_inserter(v))
#define seti(x,y,v) set_intersection(x.begin(),x.end(),y.begin(),y.end(),back_inserter(v))
#define setdu(x,y,v) set_symmetric_difference(x.begin(),x.end(),y.begin(),y.end(),back_inserter(v))
#define setd(x,y,v) set_difference(x.begin(),x.end(),y.begin(),y.end(),back_inserter(v))
#define toupper(s) transform(s.begin(),s.end(),s.begin(),::toupper)
#define tolower(s) transform(s.begin(),s.end(),s.begin(),::tolower)
const int MAX=1e9+7;
const int MOD=998244353;
const int NN = 105;
int dp[NN][NN];
int mp[NN][NN];
pii MOV[4]={{1,0},{-1,0},{0,-1},{0,1}};
int dfs(pii POS){
	int &now = dp[POS.fi][POS.se];
	if(now!=-1) return now;
	now = 1;
	fr(i,0,4){
		pii nxt = {POS.fi+MOV[i].fi,POS.se+MOV[i].se};
		if(mp[POS.fi][POS.se]>mp[nxt.fi][nxt.se]){
			now = max(now,dfs(nxt)+1);
		}
	}
	return now;
}
inline void solve(){

	string name;
	cin >> name;
	int a,b;
	cin >> a >> b;
	
	frc(i,0,a+1) mp[i][0] = mp[i][b+1] = MAX;
	frc(i,0,b+1) mp[0][i] = mp[i][a+1] = MAX;
	
	frc(i,1,a){
		frc(j,1,b){
			cin >> mp[i][j];
			dp[i][j] = -1;
		}
	}
	
	int ans = INT_MIN;
	frc(i,1,a){
		frc(j,1,b) ans = max(ans,dfs({i,j}));
	}
	cout << name << ": " << ans<<endl;
}
signed main(){
	IO;
	GETOUT;
	int t;
	cin >> t;
	while(t--)solve();
	//cerr << "Time: " << (double)clock() / (double)CLOCKS_PER_SEC << '\n';
	return 0;
}

```


