CodeForces - 995C Leaving the Bar (贪心 + 随机)
题目链接
题目大意:
给定n个向量,你可以改变他们的方向,即对于每个向量vi ,可以是vi or -vi。使得所有相加之后的模 的绝对值 <=1.5 * 1e6;
题目思路:
可以想出一种不完全对但是大致对的贪心方案,就是对于每个向量取正还是负,去计算它们是取正绝对值更小还是取负绝对值更小。
然而这样只能过一部分样例,后来听别人讲写个死循环,多次贪心即可。
其实就是随机给出每个向量的正负,但是这个代码是把向量的顺序打乱,按我们之前的方案贪心。他们的本质是一样的,但是这个会比随机给出每个向量的正负更快找到正解。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
struct node {
int id;
ll x, y;
} data[maxn];
int ans[maxn];
int main()
{
srand(time(NULL));
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%lld %lld", &data[i].x, &data[i].y);
data[i].id = i;
}
while(true) {
ll tmp = 0;
ll prex = data[1].x, prey = data[1].y;
ans[data[1].id] = 1;
ll t1, t2;
for(int i = 2; i <= n; i++) {
ll tx1 = prex - data[i].x;
ll ty1 = prey - data[i].y;
t1 = tx1 * tx1 + ty1 * ty1;
ll tx2 = data[i].x + prex;
ll ty2 = data[i].y + prey;
t2 = tx2 * tx2 + ty2 * ty2;
if(t1 < t2) {
ans[data[i].id] = -1;
prex = tx1;
prey = ty1;
}
else {
ans[data[i].id] = 1;
prex = tx2;
prey = ty2;
}
}
if(min(t1, t2) <= 2250000000000LL) {
break;
}
else {
random_shuffle(data + 1, data + n + 1);
}
}
for(int i = 1; i <= n; i++)
printf("%d%c", ans[i], i == n ? '\n' : ' ');
}