zoukankan      html  css  js  c++  java
  • 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(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 个点,每个点有个权值,点与点之间可以连成线段,线段的权值就是两个端点的权值乘积。任意两个点与原点不可能在一条直线上,求一条直线穿过的线段的最大权值和?
     
    思路:我们可以想到,有一条过原点的直线,那么直线穿过的线段都是由直线两侧的点互相连线组成的线段,进一步发现线段的权值和就是两侧的点权值和的乘积。有了前面的简化,我们可以对所有的点按照斜率进行排序,从最小斜率的点开始遍历计算,每次以过当前点的原点的直线为直线,那么我们需要计算两侧点权值和的乘积,那么复杂度是O(n*n)。我们可以优化:第一次以O(n) 遍历计算直线两侧的权值和,那么紧接着的下一次的直线划分的上下两侧只有上次的那个点不同,所以只需要O(1)的考虑上次直线上的那么点是应该加入上侧还是下侧。 所以这部分的做法是O(n) 的,但因为斜率排序是O(n*logn)的,所以整体的复杂度是
    O(n*logn)的。
     
    代码如下:
    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    typedef long long LL;
    const LL N=5e4+5;
    const double INF=1e18;
    struct Node{
        LL x,y;
        LL v;
        double f;
    }a[N];
    
    void cal(Node& t)
    {
        LL x=t.x;
        LL y=t.y;
        if(x==0) t.f=INF;
        else{
            t.f=(double)y*1.0/(double)x;
        }
    }
    LL cmp(const Node s1,const Node s2)
    {
        return s1.f<s2.f;
    }
    bool check(Node a,Node b)
    {
        if(((a.x*b.y-a.y*b.x)*1.0/a.x)>=0.0)
            return true;
        return false;
    }
    
    int main()
    {
        LL T; cin>>T;
        while(T--)
        {
            LL n; scanf("%lld",&n);
            LL tot=0;
            for(LL i=1;i<=n;i++)
            {
                scanf("%lld%lld%lld",&a[i].x,&a[i].y,&a[i].v);
                tot+=a[i].v;
                cal(a[i]);
            }
            if(n==1) { puts("0"); continue; }
            sort(a+1,a+n+1,cmp);
            LL ans=0,tmp1=0,tmp2=0;
            tmp1=a[1].v;
            for(LL i=2;i<=n;i++)
            {
               if(!check(a[1],a[i]))
                tmp1+=a[i].v;
            }
           tmp2=tot-tmp1;
           ans=max(tmp1*tmp2,ans);
           if(a[1].x<0) tmp1-=a[1].v;
           for(LL i=2;i<=n;i++)
           {
               if(a[i].x>=0) tmp1+=a[i].v;
               tmp2=tot-tmp1;
               ans=max(tmp1*tmp2,ans);
               if(a[i].x<0) tmp1-=a[i].v;
           }
           printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    智能问答系统构思(持续更新)
    软件测试
    Android实现智能问答机器人(四) -----连接我们的系统
    软件架构模式---分层架构V2.0
    软件架构模式---分层架构
    PHP文件上传示例
    PHP文件上传常见类型checklist
    PHP操作Mysql数据库查询数据实例
    PHP操作Mysql数据库更新数据实例
    PHP 操作Mysql数据库删除数据示例
  • 原文地址:https://www.cnblogs.com/chen9510/p/7367878.html
Copyright © 2011-2022 走看看