百練1088 DP+DFS
題幹在最後。
這道題本來是一道DP的練習題,的真不好意思的是,盡管那道更復雜的poj1661我最終做出來了,可是花太多時間了!我決定改變學習策略,多看別人的,等有底子了,再自己來!
要知道國外一位偉人曾說過這樣的話:
年輕人,不要總想著創造,先學習再說。
——沃·茲基碩德
不過說實話,我真的覺得自己思考思考,不會了就看看別人的寫法,前期別硬肛,這樣效率真的會高很多,而且容易有意外收獲:
這道題的move數組真的驚艷到我了,一下子省了好多代碼!
以後數組四連塊就這樣遍歷,數組八連塊就用UVA572中的方法遍歷()
四連塊BFS遍歷:
int move[][2]={0,1,0,-1,1,0,-1,0}; void BFS(int i,int j){ //輸入點的坐標 int x1,y1; for(int l=0;l<4;l++){ x1=x,y1=y; x1+=move[l][0]; y1+=move[l][1]; if( check(x1,y1) ) //check檢測邊界條件BFS(x1,y1); } }
八連塊BFS遍歷:
void BFS(int x,int y){ if(!check()) return; //邊界檢測;當然,也可以放在第二層for裏面,這樣可能還能減少遞歸棧調用 for(int dx=-1;dx<=1;dx++) for(int dy=-1;dy<=1;dy++){ if(dx!=0 || dy!=0) BFS(x+dx,y+dy); } }
本題ac代碼:(那句給dp[][]賦初值為0的,要不要都行,而且效率差不多,要的話是不是更規範?)
#include<stdio.h> #define maxn 100+10 int dp[maxn][maxn],map[maxn][maxn],move[][2]={-1,0,1,0,0,1,0,-1},ans,m,n; int boundary(int x,int y){ return x<m && x>=0 && y<n && y>=0; } int dp1(int x,int y){ if(dp[x][y]) return dp[x][y]; int x1,y1,ans=1; for(int i=0;i<4;i++){ x1=x,y1=y; x1+=move[i][0],y1+=move[i][1]; if(boundary(x1,y1) && map[x1][y1]<map[x][y]) ans=ans>(dp1(x1,y1)+1)?ans:(dp1(x1,y1)+1); } return dp[x][y]=ans; } int main(){ freopen("in.txt","r",stdin); scanf("%d%d",&m,&n); for(int i=0;i<m;i++) for(int j=0;j<n;j++){ scanf("%d",&map[i][j]); // dp[i][j]=0; //這句要不要都行 } for(int i=0;i<m;i++) for(int j=0;j<n;j++){ dp[i][j]=dp1(i,j); if(dp[i][j]>ans) ans=dp[i][j]; } printf("%d",ans); return 0; }
題幹:
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-1。當然25-24-23-...-3-2-1更長。事實上,這是最長的一條。
Input
輸入的第一行表示區域的行數R和列數C(1 <= R,C <= 100)。下面是R行,每行有C個整數,代表高度h,0<=h<=10000。
Output
輸出最長區域的長度。
Sample Input
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
Sample Output
25
百練1088 DP+DFS