洛谷P2625 豪华游轮

题目链接:

题目

题目分析:

显然可以把过程分成以下几个过程

  • 往前把能走的走完
  • 向后转最接近\(180°\)的度数
  • 向后把能走的走完
  • 原地转完剩下的旋转操作
    最后一步可以不用管,因为反正没有产生位移

需要操作一下的就是向后转的动作,用类似\(0/1\)背包的思想\(DP\)一下,然后余弦定理一下即可

代码:

#include<bits/stdc++.h>
using namespace std;
inline int read() {
	int cnt = 0, f = 1; char c = getchar();
	while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
	while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + (c ^ 48); c = getchar();}
	return cnt * f;
}
int n, x, f, b, p = 1e3;
const double PI = 3.1415926535;
int trn[55], cnt;
double ans;
bool dp[55][361];
char c[10];
int main() {
	n = read();
	for (register int i = 1; i <= n; ++i) {
		scanf("%s", c + 1), x = read();
		if (c[1] == 'f') f += x;
		if (c[1] == 'b') b += x;
		if (c[1] == 'r') trn[++cnt] = -x;
		if (c[1] == 'l') trn[++cnt] = x;
	}
	ans += f;
	dp[0][0] = 1;
	for (register int i = 1; i <= cnt; ++i)
		for (register int j = 0; j < 360; ++j)
			if (dp[i - 1][j] == 1) 
				dp[i][j] = 1, dp[i][(j + trn[i] + 360 * 10) % 360] = 1;
	
	for (register int i = 0; i < 360; ++i)
	 	if (dp[cnt][i] == 1) p = min(p, abs(i - 180));
	
	ans = sqrt(f * f + b * b + 2 * b * f * cos(p * PI / 180));
	printf("%.6lf", ans);
	return 0;
}
posted @ 2019-10-06 14:44  kma_093  阅读(147)  评论(0编辑  收藏  举报