滑雪 POJ - 1088 (基礎dp)
阿新 • • 發佈:2018-11-19
這道題是一道比較基礎的dp問題, 最開始我用成Dfs來寫, 不出意外果然超時了
定義這道題的狀態dp[i][j]為 : 從i行j列出發的最大滑行長度
狀態轉移方程應該就是: dp[i][j] = max(dp[i][j], dp[i-1][j] | h[i][j] > h[i-1][j]), max(dp[i][j], dp[i+1][j] | h[i][j] > h[i+1][j]),
max(dp[i][j], dp[i][j-1] | h[i][j] > h[i][j-1]),max(dp[i][j], dp[i][j+1] | h[i][j] > h[i][j+1])
然後牽扯到一個順序問題, 這道題目不能直觀的從前到後或從後到前, 需要對高度進行從小到大排序, 再依次遍歷
同時注意初始化問題和邊界問題, 各點初始化為1, 同時注意對越界情況的判斷
//滑雪 #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <string> #include <vector> #include <queue> #include <cmath> using namespace std; #define ms(x, n) memset(x,n,sizeof(x)); typedef long long LL; const LL maxn = 110, maxh = 10010; int R, C; int dp[maxn][maxn]; //從i行j列出發的最大長度 int height[maxn][maxn]; //高度 struct Point{ int x, y, h; //座標和高度; }s[maxn*maxn]; bool cmp(Point a, Point b){ return a.h < b.h; //按高度從小到大排序 } int solve() { for(int i = 0; i <= R+1; i++) for(int j = 0; j <= C+1; j++) dp[i][j] = 1; //初始化為1 sort(s+1, s+R*C+1, cmp); for(int i = 1; i <= R*C; i++){ if(s[i].x+1<=R && height[s[i].x][s[i].y] > height[s[i].x+1][s[i].y]) dp[s[i].x][s[i].y] = max(dp[s[i].x][s[i].y], dp[s[i].x+1][s[i].y]+1); //切記只有選了才+1 if(s[i].x-1>0 && height[s[i].x][s[i].y] > height[s[i].x-1][s[i].y]) dp[s[i].x][s[i].y] = max(dp[s[i].x][s[i].y], dp[s[i].x-1][s[i].y]+1); if(s[i].y+1<=C && height[s[i].x][s[i].y] > height[s[i].x][s[i].y+1]) dp[s[i].x][s[i].y] = max(dp[s[i].x][s[i].y], dp[s[i].x][s[i].y+1]+1); if(s[i].y-1>0 && height[s[i].x][s[i].y] > height[s[i].x][s[i].y-1]) dp[s[i].x][s[i].y] = max(dp[s[i].x][s[i].y], dp[s[i].x][s[i].y-1]+1); } int ans = 0; for(int i = 1; i <= R; i++) for(int j = 1; j <= C; j++) ans = max(ans, dp[i][j]); return ans; } int main() { cin >> R >> C; int no = 1; for(int i = 1; i <= R; i++) for(int j = 1; j <= C; j++){ cin >> height[i][j]; s[no].x = i, s[no].y = j, s[no].h = height[i][j]; no++; } cout << solve() << endl; return 0; }