URAL 1119 Metro

简单的dp

题目大意是给一个网格

然后有一些近路

求从(0,0)到(M,N)的最短距离

-------------------------------解释题目的分割线----------------------

很显然每个非边界的点可以从下面的点或者左边的点走过来

特别的 如果有近路 还要考虑近路

在这几个情况中取得最小值

那么有状态转移式  dp[i][j]=min(dp[i-1][j],dp[i][j-1])+100;
                    if(存在近路) dp[i][j]=min(dp[i][j],dp[i-1][j-1]+根号二*100);

(注意边界的处理

------------------------------我也不知道我是什么的分界线---------

要是说坑点的话 四舍五入应该算一个

其他的就不知道了


一次过~
          

#include<cstdio>
#include<cstring>
#include<algorithm>
//#define DEBUG
using namespace std;
const double INF=10000.0;
bool xy[1005][1005];
double dp[1005][1005];

int main(){
    int n,m;
    double two=1.414213;
    while(~scanf("%d %d",&m,&n)){
        memset(xy,0,sizeof(xy));
        memset(dp,0,sizeof(dp));
        dp[0][0]=0;
        int k;
        scanf("%d",&k);
        int a,b;
        while(k--){
            scanf("%d %d",&a,&b);
            xy[a][b]=true;
        }
        for(int i=0;i<=m;i++)
            for(int j=0;j<=n;j++){
                if(i==0 || j==0){
                    if(j!=0)
                        dp[i][j]=dp[i][j-1]+1;
                    if(i!=0)
                        dp[i][j]=dp[i-1][j]+1;
                    if(i==0 && j==0)
                        dp[i][j]=0;
                }
                else{
                    dp[i][j]=min(dp[i-1][j],dp[i][j-1])+1;
                    if(xy[i][j]) dp[i][j]=min(dp[i][j],dp[i-1][j-1]+two);
                }
            }
        #ifdef DEBUG
         for(int i=m;i>=0;i--)
            for(int j=0;j<=n;j++)
                printf(j<n?"%.2lf ":"%.2lf\n",dp[i][j]);
        #endif // DEBUG
        int ans=dp[m][n]*100+0.5;
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(URAL 1119 Metro)