杭电暑期多校集训— hard challenge

Hard challenge

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 579    Accepted Submission(s): 235


Problem Description
There are  n points on the plane, and the  ith points has a value  vali, and its coordinate is  (xi,yi). It is guaranteed that no two points have the same coordinate, and no two points makes the line which passes them also passes the origin point. For every two points, there is a segment connecting them, and the segment has a value which equals the product of the values of the two points. Now HazelFan want to draw a line throgh the origin point but not through any given points, and he define the score is the sum of the values of all segments that the line crosses. Please tell him the maximum score.
 

Input
The first line contains a positive integer  T(1T5), denoting the number of test cases.
For each test case:
The first line contains a positive integer  n(1n5×104).
The next  n lines, the  ith line contains three integers  xi,yi,vali(|xi|,|yi|109,1vali104).
 

Output
For each test case:
A single line contains a nonnegative integer, denoting the answer.
 

Sample Input
 
   
2 2 1 1 1 1 -1 1 3 1 1 1 1 -1 10 -1 0 100
 

Sample Output
 
   
1 1100
 这个题可以理解为现在给你n个点,每个点都有相应的权值,你可以任意连接两个点形成线段,线段 的权值为两个端点的权值之积,所有的线段都不会经过原点。现在你找一条经过原点的直线,直线的 权值为经过的线段的权值之和,最后输出这条直线可能最大的权值。
解题思路




                    P1                   P2




                 P3                         P4 


                                  Ans=P1*(P2+P4)+P3*(P2+P4)
                                      =(P1+P3)*(P2+P4)




如图所示,蓝色线为由Y轴旋转而来,两边的点互相配对,此时形成的所有的线段的权值之和即为当 所求直线在这个位置的权值,接下来只需要求出当这个直线在不同位置的时的权值并找出最大值即可。
#include
#include
#include
#define PI 3.1415926
using namespace std;
struct point
{
    int x,y,val;
    double angle;
} P[50005];

bool cmp(point p1,point p2)
{
    return p1.angle0)
                    P[i].angle=PI/2.0;
                Else
                P[i].angle=-PI/2.0;
            }
            else
                P[i].angle=atan(P[i].y*1.0/P[i].x);
        }
        sort(P,P+n,cmp);
        ans=1;
        left_sum=right_sum=0;
        //初始先以y轴对做表面进行划分
        for(int i=0; i=0)
                right_sum+=P[i].val;   //出现在y轴右侧(包含y轴)的点全部添加到右区间
            else
                left_sum+=P[i].val;
        }
        //直线左侧的点一定能和直线右侧的点连成线段,那么直线两端任意两点权值积的和,就是两个区间权值和的积
        ans=left_sum*right_sum;
        for(int i=0; i=0)                   //原来在右区间,从右区间剔除
            {
                right_sum-=P[i].val;
                left_sum+=P[i].val;
            }
            else                            //原来在左区间,从左区间剔除
            {
                right_sum+=P[i].val;
                left_sum-=P[i].val;
            }
            ans=max(ans,left_sum*right_sum);
        }
        cout<




你可能感兴趣的:(杭电暑期多校集训— hard challenge)