• 洛谷 P1434 [SHOI2002]滑雪


    洛谷 P1434 [SHOI2002]滑雪

    题目传送门

    题目描述

    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
    

    一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为 2424-1717-1616-11(从 2424 开始,在 11 结束)。当然 2525-2424-2323-ldots…-33-22-11 更长。事实上,这是最长的一条。

    输入格式

    输入的第一行为表示区域的二维数组的行数 RR 和列数 CC。下面是 RR 行,每行有 CC 个数,代表高度(两个数字之间用 11 个空格间隔)。

    输出格式

    输出区域中最长滑坡的长度。

    输入输出样例

    输入 #1复制

    输出 #1复制

    说明/提示

    对于 100%100% 的数据,1leq R,Cleq 1001≤R,C≤100。

    题解:

    作为一道记忆化搜索的题,我硬是拿DP做的。

    作为本蒟蒻恢复训练后的第一道题

    一开始想的很简单,非常容易得知状态是(dp[i][j])表示到达((i,j))点的最长滑雪路径,最后从头到尾统计一遍最大的(dp[i][j])就是答案了。

    然后开始转移,就是如果((i,j))周围的四个点比这个点高(因为只有高的能往低处滑),就更新(dp[i][j])取最大就可以。

    然后挂。

    百思不得其解(果然半年停训停傻了)我觉得思路比较完美,因为是一道黄题,觉得思维强度也就应该是这水平(逃)

    后来发现,我直接扫描的转移不是最优的。就是因为转移的时候还没有计算的那部分有可能更优,然而还没来得及被计算。

    就像这样:(显示的是DP数组)

    2 5 3 6 9 8
    2 6 6 1 1 1
    1 1 1 1 1 1
    1 1 1 1 1 1
    1 1 1 1 1 1
    

    当前转移到第二行第四列,但是只能从上、左两个状态转移得到,事实上右、下的状态有可能更优。所以导致答案统计不全。

    那么怎么办呢?

    这就涉及到了DP顺序的问题。以我看来,DP顺序需要满足两种条件:第一种,转移最优,第二种,无后效性。

    我们分析问题容易得出,如果先统计低的,后统计高的,那么就不会有转移上的问题。在当前点,只有比它低的能转移到它。

    所以把矩阵所有的值进行排序,然后用结构体构建映射。最后按照这个顺序来转移就可以。整个过程可以用优先队列实现。

    代码:

    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn=110;
    int n,m,ans;
    int map[maxn][maxn];
    int dp[maxn][maxn];//dp[i][j]表示(i,j)点的最长路
    struct node
    {
        int x,y,val;
    }a[10010];
    int tot;
    struct cmp
    { 
        bool operator()(node x,node y)
        {
            return x.val<y.val;
        }
    };
    priority_queue <node,vector<node>,cmp> q;
    void judge(int x,int y)
    {
        if(map[x-1][y]>map[x][y])
            dp[x][y]=max(dp[x][y],dp[x-1][y]+1);
        if(map[x+1][y]>map[x][y])
            dp[x][y]=max(dp[x][y],dp[x+1][y]+1);
        if(map[x][y-1]>map[x][y])
            dp[x][y]=max(dp[x][y],dp[x][y-1]+1);
        if(map[x][y+1]>map[x][y])
            dp[x][y]=max(dp[x][y],dp[x][y+1]+1);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&map[i][j]);
                dp[i][j]=1;
                a[++tot].val=map[i][j];
                a[tot].x=i;
                a[tot].y=j;
                q.push(a[tot]);
            }
        while(!q.empty())
        {
            node now=q.top();
            int xx=now.x;
            int yy=now.y;
            judge(xx,yy);
            q.pop();
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                ans=max(ans,dp[i][j]);
        printf("%d",ans);
        return 0;
    }
    
  • 相关阅读:
    Prime Cryptarithm
    Barn Repair
    Mixing Milk
    June Challenge 2017
    Dual Palindromes
    数学专题
    遗传算法学习
    UVA 11464 暴力+位运算 ***
    233
    hdu 3236 二维背包
  • 原文地址:https://www.cnblogs.com/fusiwei/p/13220790.html
Copyright © 2020-2023  润新知