# 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; } ```