hdu 6127

http://acm.hdu.edu.cn/showproblem.php?pid=6127

题意:有N个点,每一个点都有一个权值,每两点可以组成一条边,每一个边的权值为两点的权值相乘,然后求一条直线可以穿过权值和最多的边为多少

思路:枚举,枚举每一个点与原点连成的直线,把所有的点分成两半,它的权值和就是两边的总和相乘。

根据极角进行排序,排序完后可以把这些点分为两部分,a部分的x是大于0的值的和,b部分的x是小于0的值的和,依次遍历这个序列,如果当前序列的点是大于0的,那么这个点可以

从a移到b,同时a,b进行更新,然后在与之前的值比较大小,最后取最大的即可

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <math.h>
 5 #include <algorithm>
 6 #define eps 1e-7
 7 using namespace std;
 8 
 9 struct Node{
10     int x,y,val;
11     double the;
12 }node[500005];
13 
14 bool cmp(const Node &a,const Node &b)
15 {
16     if(a.the-b.the>1e-7)
17         return true;
18     else
19         return false;
20 }
21 
22 int main()
23 {
24     int t,n;
25     scanf("%d",&t);
26     while(t--)
27     {
28         scanf("%d",&n);
29         for(int i = 1;i<=n;i++)
30         {
31             scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].val);
32             node[i].the = atan(1.0*node[i].y/node[i].x);
33         }
34         int suml,sumr;
35         long long ans;
36         suml = sumr = ans = 0;
37            sort(node+1,node+1+n,cmp);
38         for(int i = 1;i<=n;i++)
39             if(node[i].x>0)
40                 suml+=node[i].val;
41             else
42                 sumr+=node[i].val;
43         ans = suml*sumr;
44         for(int i = 1;i<=n;i++)
45         {
46             if(node[i].x>0)
47                 suml-=node[i].val,sumr+=node[i].val;
48             else
49                 suml+=node[i].val,sumr-=node[i].val;
50             ans = max(ans,(long long)suml*sumr);
51         }
52         printf("%lld
",ans);
53     }
54     return 0;
55 }
原文地址:https://www.cnblogs.com/Tree-dream/p/7372012.html