Live2d Test Env

HDU - 6127: Hard challenge(扫描线,atan)

pro:给定N个二维平面的关键点,保证两点连线不经过原点。现在让你安排一条经过原点,但是不经过关键点的直线,使得两边的和的乘积最大。

sol:由于连线不经过原点,所以我们极角排序即可。

具体:因为我们的直线只需要180°,所以我们用atan(y/x)来排序,atan的范围是(-pi/2,pi/2); 而不是atan2。 这样的话,我们需要特殊处理y轴上的点。 由于没有两个同时在y轴上,所以我们可以把他看成y轴旁边的,这样不影响结果。   然后就是旋转这个直线,分成点在头部或者尾部来讨论加入还是移除。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=200010;
const double pi=acos(-1.0);
struct point{
    ll x,y,val;
    double angle;
}a[maxn];
bool cmp(point w,point v){
    return w.angle<v.angle;
}
int main()
{
    int T,N; ll ans; ll x,y;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&N);  ans=x=y=0;
        rep(i,1,N) {
           scanf("%lld%lld%lld",&a[i].x,&a[i].y,&a[i].val);
           if(a[i].x==0) a[i].angle=0.5*pi;
           else a[i].angle=atan(1.0*a[i].y/a[i].x);
        }
        sort(a+1,a+N+1,cmp);
        rep(i,1,N) if(a[i].x<0) x+=a[i].val; else y+=a[i].val;
        ans=x*y;
        rep(i,1,N){
            if(a[i].angle<=0){
               if(a[i].y<0||(a[i].x>0&&a[i].y==0)) x+=a[i].val,y-=a[i].val;
               else x-=a[i].val,y+=a[i].val;
            }
            else {
               if(a[i].y>0) x+=a[i].val,y-=a[i].val;
               else x-=a[i].val,y+=a[i].val;
            }
            ans=max(ans,x*y);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2019-04-21 19:32  nimphy  阅读(187)  评论(0编辑  收藏  举报