题目链接:http://codeforces.com/contest/983/problem/C
按照题解的dp写的,关键点在于,每次电梯接人的时候,电梯里最多有3个人,所以,只用记录三个人想去那几个楼层,记忆化搜索一下就好了。貌似在这个状态挺难设计的啊?
代码:
#include<bits/stdc++.h> #define pb push_back using namespace std; const int MAXN=2005; const int INF=0x3f3f3f3f; int a[MAXN],b[MAXN]; int dp[MAXN][1005]; int n; inline vector<int> split(int x) { vector<int> ret; for(int i=0;i<3;i++) { if(x%10) ret.pb(x%10); x/=10; } return ret; } inline int merge(vector<int> &v,int x) { int ret=0; for(int i=0;i<3;i++) { ret*=10; if(i<v.size()&&v[i]!=x) ret+=v[i]; } return ret; } inline int get1(int l,int r,int x) { return min(abs(x-l),abs(x-r))+r-l; } inline int get2(int l,int r,int x1,int x2) { return min(abs(x1-l)+abs(x2-r),abs(x1-r)+abs(x2-l))+r-l; } int dfs(int p,int cur) { int &ans=dp[p][cur]; if(ans!=-1) return ans; int pos=a[p]; vector<int> v=split(cur); v.pb(b[p]); sort(v.begin(),v.end()); if(p==n-1) { ans=get1(v[0],v.back(),pos); return ans; } ans=INF; int nxt=a[p+1]; if(v.size()<4) ans=min(ans,dfs(p+1,merge(v,nxt))+abs(nxt-pos)); for(int i=0;i<v.size();i++) { if(i&&(v[i]==v[i-1])) continue; for(int j=i;j<v.size();j++) { if(j<int(v.size())-1&&v[j]==v[j+1]) continue; int tmp=get2(v[i],v[j],pos,nxt); vector<int> tv; for(int k=0;k<v.size();k++) { if(k<i||k>j) tv.pb(v[k]); } ans=min(ans,tmp+dfs(p+1,merge(tv,nxt))); } } return ans; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d",&a[i],&b[i]); memset(dp,-1,sizeof(dp)); printf("%d\n",dfs(0,0)+a[0]-1+2*n); return 0; }