• Ural(Timus) 1119. Metro


    DP(网格DP+空间压缩)

    题意:给你一个网格,最左下角下标为(0,0),最右上角坐标(N,M),每个格子都是100*100的正方形,从当前点可以向上下左右4个方向移动,如果恰好当前点有对角线,还可以向对角线移动。另外给你K个坐标,表示那些方格有对角线,这些坐标是方格的右上角的坐标,好像(50,50),其实就是(49,49)和(50,50)有斜线连接,(34,67)其实就是(33,66)和(34,67)有连接。现在问你从(0,0)到(N,M)的最短距离,结果四舍五入为整数

    DP思想还是很简单的,但是要压缩空间否则会MLE。先说说一开始的思路

    1.首先,从当前出发,不可能向左或者向下或者向左下走,只可能向上,向右或者向右上走,所以设dp[i][j],表示在坐标(i,j)到(N,M)的最短路。那么初始化dp[N][M]=0;其余点均为INF,我们要的状态是dp[0][0]。然后用记忆化搜索,实现这样需要一个1000*1000的dp数组.

    2.回顾上面说的,不可能向左,下,左下走,其实是什么,只能在当前这一行走,或者走向下一行。所以其实我们只需要知道一行的信息——知道了前一行每个点的最短路估计值,用他们来更新这一行的最短路估计值。这样我们就可以采用递推的方式来实现

    用一个dp[2][1000]的数组,dp[1][j]表示(0,0)到当前这一行,列为j的点的最短路,dp[0][j]表示当前这一行的前一行。可见“当前行”和“前一行”是一个相对的概念,在不断替换着。

    那么状态转移方程也是很容易写出的

    dp[1][j]=min{ dp[1][j-1]+100  ,   dp[0][j]+100  ,  dp[0][j-1]+sqrt(20000.0) }

    详细看代码

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #define inf 100000000.000
    #define MAX 1010
    double dp[2][MAX];
    bool node[MAX][MAX];
    int N,M,K;
    const double D=sqrt(1.*100*100+1.*100*100);
    
    void DP()
    {
        for(int j=0; j<=M; j++)
            dp[0][j]=dp[1][j]=inf;
        dp[1][0]=0;
    
        int c=0;
        while(c<=N)
        {
            for(int j=0; j<=M; j++)
            {
                if(j-1>=0 && dp[1][j-1]+100 < dp[1][j])
                    dp[1][j]=dp[1][j-1]+100;
                
                if(dp[0][j]+100 < dp[1][j])
                    dp[1][j]=dp[0][j]+100;
                
                if(node[c][j] && j-1>=0 && dp[0][j-1]+D < dp[1][j])
                    dp[1][j]=dp[0][j-1]+D;
    
            }
    
            for(int j=0; j<=M; j++)
            {
                dp[0][j]=dp[1][j];
                dp[1][j]=inf;
            }
            c++;
        }
    
        printf("%.0f\n",dp[0][M]);
    
        return ;
    }
    int main()
    {
        while(scanf("%d%d",&N,&M)!=EOF)
        {
            scanf("%d",&K);
            int x,y;
            memset(node,0,sizeof(node));
            for(int i=0; i<K; i++)
            {
                scanf("%d%d",&x,&y);
                node[x][y]=1;
            }
            DP();
        }
        return 0;
    }
  • 相关阅读:
    论分治与归并思想
    关于缩短cin时间的方法
    【lower_bound、upperbound讲解、二分查找、最长上升子序列(LIS)模版】
    getDomain(url)-我的JavaScript函数库-mazey.js
    jQuery-PHP跨域请求数据
    ASP-Server.Transfer-Response.Redirect
    jQuery获取相邻标签的值
    分界线<hr/>
    jQuery获取input复选框的值
    Bootstrap支持的JavaScript插件
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2868571.html
Copyright © 2020-2023  润新知