1. 程式人生 > >HDU 6127 Hard challenge【極角排序】

HDU 6127 Hard challenge【極角排序】

題目來戳呀

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(1≤T≤5), denoting the number of test cases.
For each test case:
The first line contains a positive integer n(1≤n≤5×104).
The next n lines, the ith line contains three integers xi,yi,vali(|xi|,|yi|≤109,1≤vali≤104).

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

Source

題意

給出n個點的座標以及此點的價值,任意兩點能連成一條線段,線段的權值是連點的價值乘積。
讓你做一條過原點且不過整數點的直線,希望這條直線經過的線段的權值之和最大,輸出這個最大權值之和。

想法

這裡寫圖片描述
記答案為ans
ans=p1*(p3+p4)+p2*(p3+p4)=(p1+p2)*(p3+p4)
直線以左的區間所有的點的價值之和×直線以右的區間所有的點的價值之和

我們初始化直線從y軸開始,將所有的點進行極角排序。
從小到大掃一遍排序後的點(相當於是直線逆時針旋轉變換)

,若本來在左區間,就趕到右區間;本來在右區間,就趕到左區間,更新左右區間的值。
最後輸出最大值即可。

其實題解就是那一個公式~配上圖很好理解的吧(^__^)
程式碼很簡單的辣~

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e4+10;
const double PI=acos(-1.0);
struct point
{
    int x,y,val;
    double ang;
}p[maxn];
bool cmp(point a,point b)
{
    return a.ang<b.ang;
}
int main()
{
    int t,n;
    long long lsum,rsum,ans;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;++i)
        {
            scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].val);
            if(p[i].x==0)///x=0不能做分母 要特殊判斷
            {
                if(p[i].y>0)
                    p[i].ang=PI/2.0;
                else
                    p[i].ang=-PI/2.0;
            }
            else
            {
                p[i].ang=atan(p[i].y*1.0/p[i].x);
            }
        }
        sort(p,p+n,cmp);///極角排序
        lsum=0,rsum=0;///初始化左右區間的值
        for(int i=0;i<n;++i)
        {
            if(p[i].x>=0)
                rsum+=p[i].val;
            else
                lsum+=p[i].val;
        }
        ans=lsum*rsum;
        for(int i=0;i<n;++i)///更換區間
        {
            if(p[i].x>=0)
            {
                rsum-=p[i].val;
                lsum+=p[i].val;
            }
            else
            {
                rsum+=p[i].val;
                lsum-=p[i].val;
            }
            ans=max(ans,lsum*rsum);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

ps:真的是最近程式碼敲的最順的了,1A(^o^)/~