HDU 6127 Hard challenge

来源:互联网 发布:优酷怎么显示没有网络 编辑:程序博客网 时间:2024/06/07 21:11

题目传送门

题意:给你n个点,每一个点都有一个权值,从原点做一条直线, 如果经过一条由两点连成的直线,得分就加两点权值的乘积,问你能得到的最大得分。

思路:将所有的点按角的大小进行排序,然后用扫描法扫描每一个点,计算出目前在直线一边的所有点的权值和,进行计算,得出最大值。

#include <algorithm>#include <cmath>#include <cstdio>#include <cstring>#include <fstream>#include <iostream>#include <list>#include <map>#include <queue>#include <set>#include <sstream>#include <stack>#include <string>#include <vector>#define MAXN 50010#define MAXE 210#define INF 10000000#define MOD 1000000007#define LL long long#define pi acos(-1.0)using namespace std;struct Point {  LL x;  LL y;  double rad;  LL v;} p[MAXN];bool cmp(const Point &x1, const Point &x2) { return x1.rad < x2.rad; }bool check(Point p1, Point p2) { return p1.x * p2.y - p1.y * p2.x >= 0; }int main() {  std::ios::sync_with_stdio(false);  int T;  cin >> T;  for (int kase = 1; kase <= T; ++kase) {    int n;    cin >> n;    LL sum = 0;    for (int i = 0; i < n; ++i) {      cin >> p[i].x >> p[i].y >> p[i].v;      sum += p[i].v;      p[i].rad = atan2(p[i].y, p[i].x);    }    LL ans = 0;    sort(p, p + n, cmp);    int L = 0, R = 0;    LL cnt = 0;    while (L < n) {      if (L == R) {        R = (R + 1) % n;      }      if (L != 0) {        cnt -= p[L].v;      }      while (L != R && check(p[L], p[R])) {        cnt += p[R].v;        R = (R + 1) % n;      }      ans = max(ans, (sum - cnt) * cnt);      ans = max(ans, (sum - cnt - p[L].v) * (cnt + p[L].v));      L++;    }    cout << ans << endl;  }  return 0;}