pku1088:滑雪

pku1088:求矩阵的最长降序路线: http://poj.org/problem?id=1088
解法1:dp+dfs记忆性搜索:dp[x][y]=max(dp[i][j]+1)((i,j)为(x,y)的上下左右点),所以要先算i,j的最优值,所以需要用到递归
code1:
#include<iostream>
#include<cstdio>
#include<cstdlib>
int v[150][150],ans[150][150],n,m;
int dx[]={0,0,-1,1};
int dy[]={-1,1,0,0};
int dp(int a,int b)
{
    if(ans[a][b]>0)return ans[a][b];       //若已算过,直接返回,不然会超时
    for(int i=0;i<4;i++)
    {
        if(a+dx[i]>=0&&a+dx[i]<n&&b+dy[i]>=0&&b+dy[i]<m&&v[a][b]>v[a+dx[i]][b+dy[i]])
        {
            if(ans[a][b]<dp(a+dx[i],b+dy[i])+1)
                ans[a][b]=dp(a+dx[i],b+dy[i])+1;
        }
    }
    return ans[a][b];
}
int main()
{
    int max;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                scanf("%d",&v[i][j]);
            }
        }
        memset(ans,0,sizeof(ans));
        max=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(max<dp(i,j))    //求出最大值
                    max=dp(i,j);
            }
        }
        printf("%d\n",max+1);
    }
}
解法2:队列bfs:先把所有点从大到小排序,由于只有大的点才会更新小的点,所以把这些点从大到小放进队列,但比较小的数被大的数更新后,会在后面出队,更新再小的数,这样的话状态数为n*n
code2:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int v[150][150],w[150*150],dp[150][150],r[150*150];
struct abc
{
    int x,y;
}q[150*150];
int dx[]={-1,1,0,0};
int dy[]={0,0,1,-1};
int cmp(int a,int b)
{
    return w[a]>w[b];
}
int main()
{
    int n,m,max,a,b,xx,yy;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int front=0,rear=0,k=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                scanf("%d",&v[i][j]);
                dp[i][j]=1;r[k++]=i*m+j;w[i*m+j]=v[i][j];
            }
        }
        sort(r,r+n*m,cmp);             //排序
        for(int i=0;i<n*m;i++)
        {
            q[rear].x=r[i]/m;q[rear++].y=r[i]%m;
        }
        max=0;
        while(rear>front)
        {
            a=q[front].x;b=q[front++].y;
            for(int k=0;k<4;k++)
            {
                xx=a+dx[k];yy=b+dy[k];
                if(xx>=0&&xx<n&&yy>=0&&yy<m&&v[a][b]>v[xx][yy])
                {
                    if(dp[xx][yy]<dp[a][b]+1)     //(a,b)更新周围四个点的状态
                    {
                        dp[xx][yy]=dp[a][b]+1;
                        if(dp[xx][yy]>max)    //取最大值
                            max=dp[xx][yy];
                    }
                }
            }
        }
        if(max==0)         //表示所有点都不用更新,如所有点的值都相同
            printf("1\n");
        else
            printf("%d\n",max);
    }
}

/*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
output:
25*/

 

  

posted on 2012-07-25 00:24  acmer-jun  阅读(164)  评论(0编辑  收藏  举报

导航