zoukankan      html  css  js  c++  java
  • HDU

    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
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    P1772 [ZJOI2006]物流运输
    P4290 [HAOI2008]玩具取名
    P1859 不听话的机器人
    P1841 [JSOI2007]重要的城市
    P2182 翻硬币
    P1908 逆序对(归并排序)
    P1010 幂次方(分治)
    P3386 【模板】二分图匹配
    P2158 [SDOI2008]仪仗队
    P1582 倒水(贪心 + lowbit)
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10746387.html
Copyright © 2011-2022 走看看