Codeforces Round #483 (Div. 1) [Thanks, Botan Investments and Victor Shaburov!] C. Elevator(dp)

题目链接: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;
}


猜你喜欢

转载自blog.csdn.net/sinat_32872703/article/details/80394643
今日推荐