poj 1088 滑雪

来源:互联网 发布:燕郊招聘淘宝客服 编辑:程序博客网 时间:2024/05/22 07:02



点击打开链接


ichael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子 
 1  2  3  4 516 17 18 19 615 24 25 20 714 23 22 21 813 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 51 2 3 4 516 17 18 19 615 24 25 20 714 23 22 21 813 12 11 10 9

Sample Output

25

题解:


1,

直接dfs过不去,你必须吧搜索过的点的最大下滑值保存下来,这样的话之后再走到该点即可直接返回,

代码如下:

#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#define ll long longusing namespace std;const int maxn=105;int n,m;int ma[maxn][maxn];int dp[maxn][maxn];int dfs(int x,int y,int h){    if(h<=ma[x][y]) return 0;    if(x<1||x>n||y<1||y>m) return 0;    if(dp[x][y]>=0) return dp[x][y];    dp[x][y]=max(max(dfs(x+1,y,ma[x][y]),dfs(x-1,y,ma[x][y])),max(dfs(x,y+1,ma[x][y]),dfs(x,y-1,ma[x][y])))+1;    return dp[x][y];}int main(){    memset(dp,-1,sizeof(dp));    scanf("%d %d",&n,&m);    for(int i=1;i<=n;++i)        for(int j=1;j<=m;++j)            scanf("%d",&ma[i][j]);    int ans=0;    for(int i=1;i<=n;++i){        for(int j=1;j<=m;++j){            int s=dfs(i,j,999999);            ans=max(ans,s);        }    }    printf("%d\n",ans);    return 0;}

2. 直接dp,

把所有点记录他的位置,按照高度排序。

        然后从低到高依次枚举,每次从后向前枚举当前可行的最大下滑高度。

610ms 很危险。

代码如下:


#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<algorithm>#define ll long longusing namespace std;const int maxn=105;int dp[maxn*maxn];int n,m;struct node{    int x,y;    int h;}p[maxn*maxn];bool cmp(node a,node b){    return a.h<b.h;}int main(){    int cnt,ans;    while(~scanf("%d %d",&n,&m)){        cnt=0;        memset(dp,0,sizeof(dp));        for(int i=1;i<=n;++i){            for(int j=1;j<=m;++j){                scanf("%d",&p[++cnt].h);                p[cnt].x=i;                p[cnt].y=j;            }        }ans=0;        sort(p+1,p+cnt+1,cmp);        for(int i=1;i<=cnt;++i){            for(int j=i-1;j>=1;--j){                if(p[i].h>p[j].h){                    if((abs(p[i].x-p[j].x)==1&&p[i].y==p[j].y)||(p[i].x==p[j].x&&abs(p[i].y-p[j].y)==1)){                        dp[i]=max(dp[i],dp[j]+1);                    }                }            }//printf("%d ",dp[i]);            ans=max(ans,dp[i]);        }        printf("%d\n",ans+1);    }    return 0;}


3.

还是dp ,方法2 的一点优化,

其实枚举到该点之后,不用枚举所有比它低的能不能走,

直接枚举他能走的,能不能更新,这样和方法一复杂度一样。

15ms

代码如下:


#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<algorithm>#define ll long longusing namespace std;const int maxn=105;int dp[maxn][maxn];int ma[maxn][maxn];int dir[4][2]={1,0,0,1,-1,0,0,-1};int n,m;struct node{    int x,y;    int h;}p[maxn*maxn];bool cmp(node a,node b){    return a.h<b.h;}int main(){    int cnt,ans;    while(~scanf("%d %d",&n,&m)){        cnt=0;        memset(dp,0,sizeof(dp));        for(int i=1;i<=n;++i){            for(int j=1;j<=m;++j){                scanf("%d",&ma[i][j]);                p[++cnt].h=ma[i][j];                p[cnt].x=i;                p[cnt].y=j;            }        }ans=0;        sort(p+1,p+cnt+1,cmp);        for(int i=1;i<=cnt;++i){            int tx=p[i].x;            int ty=p[i].y;            for(int j=0;j<4;++j){                int xi=tx+dir[j][0];                int yi=ty+dir[j][1];                if(xi<1||xi>n||yi<1||yi>m) continue;                if(ma[tx][ty]>ma[xi][yi])                    dp[tx][ty]=max(dp[tx][ty],dp[xi][yi]+1);            }            ans=max(ans,dp[tx][ty]);        }        printf("%d\n",ans+1);    }    return 0;}



原创粉丝点击