• [机房测试] 出租车


    Description

    出租车有k个停靠点,这k个停靠点依次排成一条直线,从左到右编号为1到k。出租车一次最多带4个人。共有n个人正在等待乘车,每个人都想从某个停靠点,去往另一个停靠点,即每个人的出发点和目的点不尽相同。这n个人到达各自上车的停靠点的时间均不相同,我们按到达时间的前后依次给这n个人编号为1到n,即先到的编号小。出租车公司有一个规定,先到的人必须比后到的人先上车,当然下车顺序则任意。

    出租车每次可以移动到相邻编号的停靠点,需要耗费一个单位的时间,每个人上车或者下车都需要耗费一个单位时间,出租车一开始为空,且位于1号停靠点,出租车最后停靠点任意,那么将则n个人送到目的地至少需要多少时间呢?(注:题目保证出租车到达时需要上车的人已到达出发点)

    (nleq 2000,kleq 10)

    Solution

    不考虑车上的人的具体编号,只记录他们的终点,然后再记录当前位置,和已经上过车的人数。转移考虑枚举上车或者下客。注意到当车满载时,必有一个人要下车,我们略去这个中间状态,直接从没满载转移到另一种没满载的状态,就可以省掉一维。复杂度 (O(nk^4))

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    const int M=11;
    const int N=2e3+7;
    
    int dp[N][M][M][M][M],n,K,u[N],v[N];
    
    inline void Min(int &x,int y){x=min(x,y);}
    inline int abs(int x){return x<0? -x:x;}
    
    int dfs(int i,int now,int x,int y,int z){
        if(i>n&&((!x)&&(!y)&&(!z))) return 0;
        int &ret=dp[i][now][x][y][z];
        if(~ret) return ret; else ret=1<<30;
        // 下车,当且仅当非空
        if(x) Min(ret,dfs(i,x,0,y,z)+abs(now-x));
        if(y) Min(ret,dfs(i,y,x,0,z)+abs(now-y));
        if(z) Min(ret,dfs(i,z,x,y,0)+abs(now-z));
        // 载人,当且仅当有人可载 
        if(i>n) return ret;
        if(x&&y&&z){
            Min(ret,dfs(i+1,v[i],x,y,z)+abs(now-u[i])+abs(u[i]-v[i]));
            Min(ret,dfs(i+1,x,v[i],y,z)+abs(now-u[i])+abs(u[i]-x));
            Min(ret,dfs(i+1,y,x,v[i],z)+abs(now-u[i])+abs(u[i]-y));
            Min(ret,dfs(i+1,z,x,y,v[i])+abs(now-u[i])+abs(u[i]-z));
        }else{
            if(!x) Min(ret,dfs(i+1,u[i],v[i],y,z)+abs(now-u[i]));
            if(!y) Min(ret,dfs(i+1,u[i],x,v[i],z)+abs(now-u[i]));
            if(!z) Min(ret,dfs(i+1,u[i],x,y,v[i])+abs(now-u[i]));
        }
        return ret;
    }
    
    int main(){
        freopen("taxi.in","r",stdin);
        freopen("taxi.out","w",stdout);
        memset(dp,-1,sizeof(dp));
        scanf("%d%d",&n,&K);
        for(int i=1;i<=n;i++) 
            scanf("%d%d",&u[i],&v[i]);
        printf("%d",dfs(1,1,0,0,0)+2*n);
    }
    
  • 相关阅读:
    win10下安装为知笔记的markdown插件
    最近一段时间的工作状态
    C++中的取余与取模
    来新项目后,最心虚的一个夜晚
    g++添加支持c++11的选项
    Linux ssh远程登陆方式:密码与公钥
    判断脚本加载完成
    解决ie6下最小高度问题
    display:inline-block的深入理解
    ff下button按钮上的文字垂直居中
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/15501029.html
Copyright © 2020-2023  润新知