P2625 豪华游轮

题目传送门
这是一道贪心为主,数学为辅的题目。

根据题目,我们可以轻松得到下列结论:先向前走(走完\(forward\)),然后通过旋转把船身尽可能调转方向(接近\(180°\)),接着走掉剩余的(\(backward\))。我们知道,为了尽可能远离出发点,必须不走回头路,所以第一,三步没问题。而对于偏转多少度,通过余弦定理可以知道,两邻边一定的情况下,设夹角为\(\alpha\)\(\cos\alpha\)越小,第三边越大,对于区间\([0,\pi]\)\(\cos\alpha\)单调递减,所以当\(\alpha=\pi\)时,\(\cos\alpha\)有最小值,第三边有最大值。

那么我们只需要考虑怎么组合能使得偏转角度接近\(180\),那么就用01背包解决,最后求距离用余弦定理解决即可。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=50+10;
int qian,hou;
int n;
int a[400],f[20000+10];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		string s;cin>>s;
		int x;cin>>x;
		if(s=="forward")qian+=x;
		if(s=="backward")hou+=x;
		if(s=="left")x%=360,a[x]++;
		if(s=="right")x%=360,a[360-x]++;
	}
	f[0]=1;
	for(int i=0;i<360;i++)
		while(a[i]--)
			for(int j=20000;j>=0;j--)
				if(f[j])f[j+i]++;
	int minn=0x7fffffff;
	for(int i=1;i<=20000;i++)
		if(f[i])minn=min(minn,abs(i%360-180));
	if(minn==0){
		cout<<qian+hou<<".000000"<<endl;
		return 0;
	}
	cout<<fixed<<setprecision(6)<<sqrt((double)qian*qian+(double)hou*hou-2*(double)qian*(double)hou*cos((double)(180-minn)*M_PI/180))<<endl;
	return 0;
}
posted @ 2023-07-21 14:55  LsmQwQ  阅读(22)  评论(0)    收藏  举报