• Aizu-2200 Mr. Rito Post Office


    题目在此:AOJ  2200

    完整翻译:翻译来源

    题目大意:

           在一些城市中有水路和陆路连接,每一条路都有长度。但是水路必须乘船,且坐船到达某个位置后船必须留在那里,下次坐必须回到该地。现在有m城市要到达,且必须按照指定的顺序,问最小代价。

    Tag

           最短路+dp

    做法:

       预处理出任意两点间只走水路或陆路的最小代价,然后考虑dp

       记状态dp[i][j]代表要到第i个任务所指定的城市且将船扔到j号城市的最小代价。可以考虑两种情况:只走陆地和陆地水路混合走/只走水路。那么转移非常显然:

       只走陆地:直接加上陆地最短路即可,船的位置不变。

       混合走/只走水路:从当前点走陆地->停船点->新的停船点->走陆地到目的地,船就停到了新的停船点。

       但是要特殊处理一下第一个点,因为它可能会先把船停到某个地方,然后再回到初始点,为后面做准备。

    复杂度:

       O(R*N^2)

    code:

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<map>
    #define RG register
    #define IL inline
    #define pi acos(-1.0)
    #define ll long long
    #define inf 1e8
    using namespace std;
    
    int n,m,R;
    long long land[300][300],water[300][300],dp[1005][300];
    int a[1005];
    
    void pre(){
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++){
              land[i][j]=land[j][i]=inf;
              water[i][j]=water[j][i]=inf;
            }
        for(int i=1;i<=n;i++)
             land[i][i]=0,water[i][i]=0;
    }
    
    void floyd(){
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++){
                    if(k==i||k==j||i==j) continue;
                    water[i][j]=min(water[i][j],water[i][k]+water[k][j]);
                    land[i][j]=min(land[i][j],land[i][k]+land[k][j]);
                }
    }
    
    int main(){
        while(1){
         scanf("%d%d",&n,&m);
         if(n==0&&m==0) break;
         pre();
         for(int i=1;i<=m;i++){
             int l,r; string str;
             long long w;
             scanf("%d%d%lld",&l,&r,&w);
             cin>>str;
             if(str=="L") land[l][r]=land[r][l]=min(land[r][l],w);
             else water[l][r]=water[r][l]=min(water[r][l],w);
        }
        floyd();
        scanf("%d",&R);
        for(int i=1;i<=R;i++)
            for(int j=1;j<=n;j++)
              dp[i][j]=inf;
        for(int i=1;i<=R;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
          dp[1][i]=water[a[1]][i]+land[i][a[1]];//第一次出发可以将船停到任意处再坐船回到当前目标点
        for(int i=2;i<=R;i++)//目的地
         for(int j=1;j<=n;j++)//上一次的下船点
           for(int type=1;type<=2;type++){
            if(type==1) dp[i][j]=min(dp[i][j],land[a[i-1]][a[i]]+dp[i-1][j]);//走陆地
            else
             for(int k=1;k<=n;k++)//新的下船点
             dp[i][k]=min(dp[i][k],dp[i-1][j]+land[a[i-1]][j]+water[j][k]+land[k][a[i]]);//走水路
            }
         long long minn=inf;
         for(int i=1;i<=n;i++)
            minn=min(minn,dp[R][i]);
         printf("%lld
    ",minn);
        }
        return 0;
    }
  • 相关阅读:
    Linux环境下搭建Git仓库
    Linux环境下安装zookeeper
    nginx: [error] open() "/var/run/nginx/nginx.pid" failed (2: No such file or directory)
    Dart语言特性必备了解!
    Flutter中打造多行列列表GridView组件的使用
    Flutter常用组件(Widget)解析-Scaffold
    Flutter常用组件(Widget)解析-ListView
    Flutter常用组件(Widget)解析-Image
    Flutter常用组件(Widget)解析-Text
    Flutter常用组件(Widget)解析-Container
  • 原文地址:https://www.cnblogs.com/cjoier-nfy/p/7620301.html
Copyright © 2020-2023  润新知