zoukankan      html  css  js  c++  java
  • AcWing 274. 移动服务

    题目链接

    https://www.acwing.com/problem/content/276/

    题目描述

    一个公司有三个移动服务员,最初分别在位置1,2,3处。

    如果某个位置(用一个整数表示)有一个请求,那么公司必须指派某名员工赶到那个地方去。

    某一时刻只有一个员工能移动,且不允许在同样的位置出现两个员工。

    从 p 到 q 移动一个员工,需要花费 c(p,q)。

    这个函数不一定对称,但保证 c(p,p)=0。

    给出N个请求,请求发生的位置分别为 p1~pN。

    公司必须按顺序依次满足所有请求,且过程中不能去其他额外的位置,目标是最小化公司花费,请你帮忙计算这个最小花费。

    输入格式
    第1行有两个整数L,N,其中L是位置数量,N是请求数量,每个位置从1到L编号。

    第2至L+1行每行包含L个非负整数,第i+1行的第j个数表示c(i,j) ,并且它小于2000。

    最后一行包含N个整数,是请求列表。

    一开始三个服务员分别在位置1,2,3。

    输出格式
    输出一个整数M,表示最小花费。

    数据范围
    3≤L≤200,
    1≤N≤1000

    输入样例

    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
    

    思路

    对于这样类型的DP题目,我们首先会想到状态的表示由f[i][a][b][c],表示完成前i个任务时三人在a,b,c的所有方案的最小花费,但是时间和空间复杂度非常大,我们应该想办法减掉任意一维就可以做了。首先遍历的基础n不能减掉,我们发现当处理完前i个任务时,一定有一个位置上有人,就是任务i的地点,所以我们只需要枚举另外两个地点即可。
    还有一个就是遍历的顺序问题,即转移方式。大部分的DP问题使用的方法是由前面所有可以到当前状态的旧状态更新新状态,如果这道题我们也这样做会发现可以到当前的状态很多,也不好分析。
    如果转化成当前状态去更新依赖它的状态即往前更新,也就只有三个总可能,即派在a或在b或在p[i]去完成第i+1个任务。所以假定第0个任务在3,f[0][1][2]=0,其他都为正无穷,那么第1个状态时只能被f[0][1][2][3]更新。
    感觉说了好多废话hhh,大佬请忽略,如果有错希望指出

    时间复杂度

    O(N*L*L)

    C++ 代码

    #include<iostream>
    #include<string.h>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<string>
    #include<set>
    #include<map>
    using namespace std;
    typedef pair<int,int> PII;
    typedef long long LL;
    const int N=210;
    int f[1010][N][N],c[N][N],p[1010];
    int main(){
        int l,n;
        cin>>l>>n;
        for(int i=1;i<=l;++i){
            for(int j=1;j<=l;++j){
                cin>>c[i][j];
            }
        }
        memset(f,0x3f,sizeof f);
        f[0][1][2]=0;
        int res=0x3f3f3f3f;
        p[0]=3;
        for(int i=1;i<=n;++i) cin>>p[i];
        for(int i=0;i<n;++i){
            for(int x=1;x<=l;++x){
                for(int y=1;y<=l;++y){
                    int z=p[i],to=p[i+1];//
                    if(x==z||y==z||x==y) continue;  //f[i][x][y][z] x,y,z三人
                    f[i+1][x][y]=min(f[i+1][x][y],f[i][x][y]+c[z][to]);//z去
                    f[i+1][z][y]=min(f[i+1][z][y],f[i][x][y]+c[x][to]);//x去
                    f[i+1][x][z]=min(f[i+1][x][z],f[i][x][y]+c[y][to]);//y去
                    if(i==n-1) res=min(min(min(res,f[i+1][x][y]),f[i+1][z][y]),f[i+1][x][z]);
                }
            }
        }
        cout<<res<<endl;
        return 0;
    }
    
    
  • 相关阅读:
    Mac上的USB存储设备使用痕迹在新版操作系统有所变化
    Beware of the encrypted VM
    A barrier for Mobile Forensics
    Second Space could let suspect play two different roles easily
    Take advantage of Checkra1n to Jailbreak iDevice for App analysis
    Find out "Who" and "Where"
    Where is the clone one and how to extract it?
    Downgrade extraction on phones running Android 7/8/9
    高版本安卓手机的取证未来
    How to extract WeChat chat messages from a smartphone running Android 7.x or above
  • 原文地址:https://www.cnblogs.com/jjl0229/p/12690303.html
Copyright © 2011-2022 走看看