HDU 6127 Hard challenge(计算几何)

Description

给出二维平面 n 个点的坐标(xi,yi)和权值 vali ,保证任意两点不重复且连线不经过原点,经过原点但不经过这 n 个点中任一点的直线,定义得分为这条直线两边点点权和的乘积,问最大得分

Input

第一行一整数T表示用例组数,每组用例首先输入一整数 n 表示点数,之后n行每行输入三个整数 xi,yi,vali 表示点的坐标和权值 (1T5,1n5104,|xi|,|yi|109,1vali104)

Output

输出最大得分

Sample Input

2
2
1 1 1
1 -1 1
3
1 1 1
1 -1 10
-1 0 100

Sample Output

1
1100

Solution

把所有点极角排序,用 y 轴开始逆时针旋转这条直线,每次把直线扫过的点放到另一侧,维护得分最大值即可

注:从y轴开始扫是因为极角最小值为 π2 atan(y/x)(π2,π2)atan2(y,x)(π,π]

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define maxn 50005
#define PI acos(-1.0)
struct node
{
    int x,y,val;
    double angle;
    bool operator<(const node&b)const
    {
        return angle<b.angle;
    }
}p[maxn];
int T,n;
int main()
{
    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)p[i].angle=0.5*PI;
            else p[i].angle=atan(1.0*p[i].y/p[i].x);
        }
        sort(p,p+n);
        ll l=0,r=0;
        for(int i=0;i<n;i++)
            if(p[i].x>=0)r+=p[i].val;
            else l+=p[i].val;
        ll ans=l*r;
        for(int i=0;i<n;i++)
        {
            if(p[i].x>=0)r-=p[i].val,l+=p[i].val;
            else r+=p[i].val,l-=p[i].val;
            ans=max(ans,l*r);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值