CodeForces - 995C Leaving the Bar(随机化、贪心)

CF995C Leaving the Bar

题目大意:

有一堆向量,你可以将一些取反,使后所有向量之和的长度小于\(1.5\times 10^6\),保证有解。

思路:

一个明显的贪心策略就是比较一下对于每一个向量取反与不取反对向量和的贡献哪个更小。

n为1e5却给了2s,题目保证有解暗示你可以乱搞

显然这样的贪心策略很容易构造出样例卡掉,但是如果我们将给定的序列进行随机化之后再贪心,则卡掉的概率大大降低,实际运行中也是跑得飞快。

Code:
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;

struct Node {
	int x, y, id;
}a[N];
int ans[N];

double dis(long long x, long long y) {
	return sqrt(1.0 * x * x + y * y);
}

int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int n; cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i].x >> a[i].y;
		a[i].id = i;
	}
	while (1) {
		int x = 0, y = 0;
		for (int i = 1; i <= n; i++) {
			if (dis(x + a[i].x, y + a[i].y) < dis(x - a[i].x, y - a[i].y)) {
				x += a[i].x, y += a[i].y;
				ans[a[i].id] = 1;
			}
			else {
				x -= a[i].x, y -= a[i].y;
				ans[a[i].id] = -1;
			}
		}
		if (dis(x, y) <= 1.5e6) {
			break;
		}
		random_shuffle(a + 1, a + 1 + n);
	}
	for (int i = 1; i <= n; i++) {
		cout << ans[i] << " ";
	}
	cout << endl;
	return 0;
}
posted @ 2021-01-17 19:17  Nepenthe8  阅读(48)  评论(0编辑  收藏  举报