问题: 找给定的图中最长下降路线的长度。
分析:可以看作dfs中的广义连通(高度作为连通的判断条件),对每个点都考虑它的连通的长度,此外,找某个点的连通长度时会有对其他点的连通长度单向调用(状态转移,dp),可以记录下来(记忆化搜索)避免重复计算。
实现:
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 const int maxn = 100+5; 5 int h[maxn][maxn], r, c, mem[maxn][maxn] = {0}; 6 bool is_out(int x, int y) 7 { 8 return (x<0 || x>r - 1 || y<0 || y>c - 1)?true:false; 9 } 10 int ad_dfs(int x,int y) { 11 int tempmax = 0, fri[4][2] = { {x - 1,y},{x + 1,y},{x,y - 1},{x,y+1} }; 12 for (int i = 0; i < 4; i++) 13 { 14 int tx = fri[i][0]; 15 int ty = fri[i][1]; 16 if (is_out(tx,ty)||h[x][y]<=h[tx][ty]) 17 continue; 18 else if(mem[tx][ty]) 19 tempmax = tempmax<mem[tx][ty]?mem[tx][ty]:tempmax; 20 else { mem[tx][ty] = ad_dfs(tx, ty);tempmax = tempmax<mem[tx][ty] ? mem[tx][ty] : tempmax;} 21 } 22 return mem[x][y]=tempmax+1; 23 } 24 int main() 25 { 26 //freopen("in.txt", "r", stdin); 27 //freopen("out.txt", "w", stdout); 28 cin >> r >> c; 29 for (int i = 0; i < r; i++) 30 for (int j = 0; j < c; j++) 31 cin >> h[i][j]; 32 int maxlen = 0; 33 for (int i = 0; i < r; i++) 34 for (int j = 0; j < c; j++) 35 { 36 ad_dfs(i,j); 37 maxlen = maxlen < mem[i][j] ? mem[i][j]:maxlen; 38 } 39 printf("%d ",maxlen); 40 return 0; 41 }
优化:减少不必要的中间量,if else 逻辑仅取成立,仅取在界内。
#include<iostream> #include<algorithm> using namespace std; const int maxn = 100+5; int h[maxn][maxn], r, c, mem[maxn][maxn] = {0}; bool is_in(int x, int y){ return (x > -1 && x<r&& y>-1 && y < c);} int ad_dfs(int x,int y) { //优化后 int fri[4][2] = { {x - 1,y},{x + 1,y},{x,y - 1},{x,y+1} }; for (int i = 0; i < 4; i++) { int tx = fri[i][0], ty = fri[i][1]; if (is_in(tx, ty)&&h[tx][ty]<h[x][y]) if(mem[tx][ty]) mem[x][y]= mem[x][y]<mem[tx][ty]+1 ? mem[tx][ty]+1 : mem[x][y]; else { mem[tx][ty] = ad_dfs(tx, ty); mem[x][y] = mem[x][y]<mem[tx][ty] + 1 ? mem[tx][ty] + 1 : mem[x][y];} } return mem[x][y]; } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); cin >> r >> c; for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) cin >> h[i][j]; int maxlen = 0; for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) { mem[i][j]=ad_dfs(i,j); maxlen = maxlen < mem[i][j] ? mem[i][j]:maxlen; } cout<<maxlen+1<<endl; return 0; }
小结:dfs的深入和dp,记忆化简化。初始化目标状态后,之后状态改变(当且仅当存在单向高度差).