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\n",ans); 53 } 54 return 0; 55 }