[BZOJ1278][向量vector][模拟+向量]
题目大意:
一个二维向量 (x,y) 的权定义为 x2+y2 。已知一个由n个二维向量组成的集合,求该集合的一个子集,使该子集中的向量和的权尽可能大。
思路:
有一个结论是,构成答案的向量一定在某一个过原点的直线一侧
所以把直线排一遍序然后维护它们在同一侧就好了。
代码:
#include <bits/stdc++.h>
using namespace std;
const int Maxn = 200010;
typedef long long ll;
inline ll Max(const ll &a, const ll &b) {
return a > b ? a : b;
}
inline char get(void) {
static char buf[1000000], *p1 = buf, *p2 = buf;
if (p1 == p2) {
p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin);
if (p1 == p2) return EOF;
}
return *p1++;
}
inline void read(ll &x) {
x = 0; static char c; bool f = 0;
for (; !(c >= '0' && c <= '9'); c = get()) if (c == '-') f = 1;
for (; c >= '0' && c <= '9'; x = x * 10 + c - '0', c = get()); if (f) x = -x;
}
struct P {
ll x, y;
P(void) {}
P(const int &x, const int &y) : x(x), y(y) {}
inline void init(void) {
read(x), read(y);
}
friend P operator + (P a, P b) {
return P(a.x + b.x, a.y + b.y);
}
friend P operator - (P a, P b) {
return P(a.x - b.x, a.y - b.y);
}
friend bool operator < (P a, P b) {
if (a.x == b.x && a.y == b.y) return 0;
return atan2(a.y, a.x) < atan2(b.y, b.x);
}
ll len(void) {
return x * x + y * y;
}
friend ll cross(P a, P b) {
return a.x * b.y - a.y * b.x;
}
} p[Maxn], now;
ll n, ans;
int main(void) {
//freopen("in.txt", "r", stdin);
read(n);
for (int i = 1; i <= n; i++) p[i].init();
sort(p + 1, p + 1 + n);
for (int i = 1; i <= n; i++) p[i + n] = p[i];
now = p[1];
for (int i = 1, j = 1; i <= n; i++) {
while (j + 1 < i + n && cross(p[i], p[j + 1]) >= 0) now = now + p[++j], ans = Max(ans, now.len());
now = now - p[i];
ans = Max(ans, now.len());
}
printf("%lld.000\n", ans);
}
完。
By g1n0st