UVA1632 阿里巴巴 Alibaba题解

简单题意:数轴上有 \(n\) 个点,已知每个点的坐标 \(a_i\) 和毁灭时间 \(t_i\) 。开始时可以选择任意一点空降,每刻可以选择向左或者向右移动 \(1\) 的单位长度,求出经过所有点的最短时间,如果不可能输出 No solution

首先因为经过点不会浪费时间,而且题目说 \(a_i\) 是有序的,所以可以通过区间 \([a_j,a_i,x]\) 表示经过此区间 \([a_j,a_i]\) ,并且当前位置是 \(x\) 的所有点消耗的最短时间。

考虑区间DP。然而因为压根不知道 \(a_i\) 的大小所以无法存下这个巨型状态,考虑优化。因为经过区间时保证每个点都被访问,贪心一下得出目前位置要么在区间最左端要么在最右段。那就以 \(f_{j,i,0}\) 表示经过区间 \([j,i]\) 并且目前在点 \(a_j\) 的最短时间,以 \(f_{j,i,1}\) 表示经过区间 \([j,i]\) 并且目前在点 \(i\) 的最短时间。

接下来考虑状态转移,也就是动规方程:

每个区间都是由 \(2\) 个小区间合并起来的,以下用 \(j\) 来表示区间左端,用 \(i\) 来表示区间右端。

\(f_{j,i,0}\) 举例子,每次要么从 \(f_{j+1,i,0}\) 向左移动过 \(1\) 个点,移动距离是 \(a_{j+1}-a_j\) ;要么从 \(f_{j+1,i,1}\) 走过 \(i-j\) 个点,移动距离是 \(a_i-a_j\)。向右转移同理。还要在每次转移结束后还要判断,如果当前时间大于等于被刚刚经过的点的摧毁时间,标记为极大值。

接下来是初始状态,因为可以从任意一点空降落地瞬间经过任意单点,所以 \(f_{i,i,0}=f_{i,i,1}=0\) 。最终答案是 \(f_{1,n,0}\)\(f_{1,n,1}\) 的较小值。如果还是出现了极大值就表示无解。

两重循环,每次是 \(10^4\) 总共是 \(10^8\) 卡卡常数就完全不会超时。对代码有较大要求看不惯 \(10^4\) 二维数组的可以写滚动数组,但是这题没必要。另外记得 UVA 是多组数据。

这里建议每个人按照自己区间 DP 中枚举左端和右端的方式写,因为方式实在是太太太多了,每次写不一样的就很容易出错。

最重要的代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using std::cin;using std::cout;
template<typename any>inline any max(any x,any y){return x>y?x:y;}
template<typename any>inline any min(any x,any y){return x<y?x:y;}
template<typename any>inline any abs(any x){return x>0?x:-x;}
struct treasure{int a,t;}a[10007];
int f[10007][10007][2];
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	std::ios::sync_with_stdio(false);
	cin.tie(nullptr);cout.tie(nullptr);
	int i,j,k;
	int n,m,T;

	while(cin>>n)
	{
		for(i=1;i<=n;i++)f[i][i][0]=f[i][i][1]=0;
		for(i=1;i<=n;i++)cin>>a[i].a>>a[i].t;
		for(i=2;i<=n;i++)for(j=i-1;j;j--)
		{
			f[j][i][0]=min(f[j+1][i][0]+a[j+1].a-a[j].a,f[j+1][i][1]+a[i].a-a[j].a);
			if(f[j][i][0]>=a[j].t)f[j][i][0]=0x3f3f3f3f;
			f[j][i][1]=min(f[j][i-1][1]+a[i].a-a[i-1].a,f[j][i-1][0]+a[i].a-a[j].a);
			if(f[j][i][1]>=a[i].t)f[j][i][1]=0x3f3f3f3f;
		}
		int ans=min(f[1][n][0],f[1][n][1]);
		if(ans==0x3f3f3f3f)cout<<"No solution\n";
		else cout<<ans<<'\n';
	}

	return 0;
}
posted @ 2022-02-14 15:11  蒟酱  阅读(59)  评论(1)    收藏  举报