poj 1088

问题: 找给定的图中最长下降路线的长度。

分析:可以看作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\n",maxlen);
40     return 0;
41 }
View Code

优化:减少不必要的中间量,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;
}
View Code

小结:dfs的深入和dp,记忆化简化。初始化目标状态后,之后状态改变(当且仅当存在单向高度差).

posted @ 2016-06-27 15:22  TechIsOnlyTool  阅读(120)  评论(0编辑  收藏  举报