Codeforces 984E

题意

一栋楼九层高,有n个人,第i个人在ai层要去bi层。有个电梯,最多坐四个人。进电梯花费1时间,出电梯花费1时间,电梯每开一层需要1时间,电梯刚开始在1楼。问把所有人送到目的地最少时间是多少。

题解

记忆化搜索可以解这道题。自己DP功底太差所以在比赛时候没做出来。首先确定状态,f[i][cur][a][b][c],表示第i个人在电梯里,电梯里其他三个人要去的目的地分别是a,b和c,其他三个人肯定是小于编号i-1的人。电梯现在在cur层。

状态转移的办法会在程序中给出。

#include<bits/stdc++.h>
using namespace std;
const int N=2005,INF=0x3f3f3f3f;
int d[N],dd[N],f[N][10][10][10][10],n;
int dfs(int i,int cur,int a,int b,int c){
    if(~f[i][cur][a][b][c]) return f[i][cur][a][b][c];
    int minn=INF;
    if(i>n){//如果所有人都已经在电梯里或者到了目的地,就把电梯里所有的人扔出去就行了
        if(a==0&&b==0&&c==0) return 0;
        if(a) minn=min(minn,dfs(i,a,0,b,c)+abs(cur-a)+1);
        if(b) minn=min(minn,dfs(i,b,a,0,c)+abs(cur-b)+1);
        if(c) minn=min(minn,dfs(i,c,a,b,0)+abs(cur-c)+1);
    }else{
        if(a) minn=min(minn,dfs(i,a,0,b,c)+abs(a-cur)+1);
        if(b) minn=min(minn,dfs(i,b,a,0,c)+abs(b-cur)+1);
        if(c) minn=min(minn,dfs(i,c,a,b,0)+abs(c-cur)+1);
        if(a&&b&&c){//如果电梯满人,就下去一个上来一个
            minn=min(minn,dfs(i+1,dd[i],a,b,c)+abs(d[i]-cur)+abs(dd[i]-d[i])+2);//送走为i的人
            minn=min(minn,dfs(i+1,a,dd[i],b,c)+abs(d[i]-cur)+abs(a-d[i])+2);//依此类推
            minn=min(minn,dfs(i+1,b,a,dd[i],c)+abs(d[i]-cur)+abs(b-d[i])+2);
            minn=min(minn,dfs(i+1,c,a,b,dd[i])+abs(d[i]-cur)+abs(c-d[i])+2);
        } else{//没满就上人
            if(!a) minn=min(minn,dfs(i+1,d[i],dd[i],b,c)+abs(cur-d[i])+1); else
            if(!b) minn=min(minn,dfs(i+1,d[i],a,dd[i],c)+abs(cur-d[i])+1); else
            minn=min(minn,dfs(i+1,d[i],a,b,dd[i])+abs(cur-d[i])+1);
        }
    }
    return f[i][cur][a][b][c]=minn;
}
int main(){
    memset(f,-1,sizeof f);
    cin>>n;
    for(int i=1;i<=n;++i) scanf("%d%d",d+i,dd+i);
    cout<<dfs(1,1,0,0,0);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/jiaangk/p/9203792.html