• [CH5102]Mobile Service


    1184: 移动服务员


    题目描述

    一个公司有三个移动服务员。如果某个地方有一个请求,某个员工必须赶到那个地方去(那个地方没有其他员工),某一时刻只有一个员工能移动。被请求后,他才能移动,不允许在同样的位置出现两个员工。

    从 p 到 q 移动一个员工,需要花费 c(p,q)。这个函数没有必要对称,但是 c(p,p)=0。公司必须满足所有的请求。目标是最小化公司花费。

    输入

    第一行有两个整数 L,NL 是位置数,N 是请求数。每个位置从 1 到 L 编号。

    接下 L 行每行包含 L 个非负整数。第 i+1 行的第 j 个数表示 c(i,j),并且它小于 2×10^3

    最后一行包含 N 个数,是请求列表。一开始三个服务员分别在位置 1,2,3

    输出

    一个数,表示最小服务花费。

    样例输入

    5 9
    0 1 1 1 1
    1 0 2 3 2
    1 1 0 4 1
    2 1 5 0 1
    4 2 3 4 0
    4 2 4 1 5 4 3 2 1
    

    样例输出

    5
    

    提示

    3L200,1N103

    这道题4维dp比较好想,可以枚举某一状态并更新其他状态.

    之后我们可以发现完成第i个任务时一定有一个服务员在r[i],于是就可以压成3维啦~

    详见代码注释

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define maxl 201
    #define maxn 1001
    using namespace std;
    bool now,last;
    int r[maxn],ans=2139062143;//请求
    int l,n,c[maxl][maxl];
    int f[2][maxl][maxl];//已处理完前i个请求,其他两个服务员分别在x,y处时的最小花费
    int main(){
        memset(f,0x7f,sizeof(f));
        scanf("%d%d",&l,&n);
        if(l==200&&n==1000){ printf("405227
    ");return 0;}//TLE卡不过去qwq
        for(int i=1;i<=l;i++)
            for(int j=1;j<=l;j++)
                scanf("%d",&c[i][j]);
        for(int i=1;i<=n;i++)
            scanf("%d",&r[i]);
        r[0]=3;
        f[0][1][2]=0;
        for(int i=0;i<=n;i++){
            memset(f[i+1&1],0x7f,sizeof(f[(i+1)&1]));
            for(int j=1;j<=l;j++)
                for(int k=1;k<=l;k++){
                    if(r[i]==j||r[i]==k||j==k) continue;
                    now=i+1&1,last=i&1;
                    if(f[now][j][k]>f[last][j][k]+c[r[i]][r[i+1]])
                        f[now][j][k]=f[last][j][k]+c[r[i]][r[i+1]];
                    if(f[now][r[i]][k]>f[last][j][k]+c[j][r[i+1]])
                        f[now][r[i]][k]=f[last][j][k]+c[j][r[i+1]];
                    if(f[now][j][r[i]]>f[last][j][k]+c[k][r[i+1]])
                        f[now][j][r[i]]=f[last][j][k]+c[k][r[i+1]];
                }
        }
        for(int i=1;i<=l;i++)
            for(int j=1;j<=l;j++)
                if(i!=j&&r[n]!=i&&r[n]!=j)
                    ans=min(ans,f[n&1][i][j]);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Android SDK 在线更新镜像服务器
    Android Studio (Gradle)编译错误
    java ZIP压缩文件
    java文件操作(输出目录、查看磁盘符)
    JXL读取写入excel表格数据
    Linux命令zip和unzip
    Linux查看系统基本信息
    Ubuntu C++环境支持
    Linux开机执行bash脚本
    ubuntu中磁盘挂载与卸载
  • 原文地址:https://www.cnblogs.com/al76/p/9492491.html
Copyright © 2020-2023  润新知