HDU 2017 多校联合训练赛7 1008 6127 Hard challenge (重载运算符)

Hard challenge

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)


Problem Description
There are n points on the plane, and the i th 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 i th 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
 

Source
2017 Multi-University Training Contest - Team 7


题目大意
给出n个点的坐标和权值val,任意两点之间都有线段连接,线段的权值是两端点权值的乘积(题目保证,没有两个点坐标相同,并且没有两个点的连线过原点)。现在要求过原点做一条直线,使直线穿过的所有线段的权值和最大。

题目分析
首先,我们要解决的问题是怎么求一条直线穿过的所有线段的权值和。现在我们在平面内任意作一条直线,我们会发现直线把平面上的所有点分成了左右两部分,假设直线右边只有一个点,左边有五个点,那么直线穿过的线段就是右边的一个点与左边的五个点的连线,线段权值和就是右边点与左边五个点的权值分别相乘的和,右边点的权值作为公共项,把它提出来,就是右边点的权值与左边点的权值和的乘积。现在假设左边还是只有五个点,右边有三个点,线段权值和就是每个右边点的权值分别与左边点的权值和的乘积,然后求和,左边点的权值和作为公共项,把它提出来,就得到这条直线穿过线段的权值和,就是左边点的权值和与右边点的权值和的乘积。

所以要找到所有直线中的最优解,就是找到直线把所有点划分为两边阵营的最优解,并且直线是过原点,所以直线斜率在两点与原点连线的斜率之间时,线段权值和是相等的。所以,我们只需要遍历所有点与原点连线的斜率形成的区间即可。

具体过程,假设我们做一条斜率为负无穷的直线,让直线斜率从负无穷向正无穷扫描。在此之前先做两件事,第一,设置sum1,sum2,分别记录在y轴右边和左边的点权和,然后ans=sum1*sum2为初始值,第二,计算所有点与直线连线的斜率,并且从小到大排序。然后,遍历所有的点(与遍历所有的区间是等效的)。

最后,再注意两点,第一,在第一,三象限的点与原点连线的斜率都是负的,所以我们在直线从斜率负无穷到正无穷扫描的过程中,先扫到的并不一定是第四象限的点,也可能是第三象限的点,但是,因为每个点对应的斜率是唯一的,所以,我们可以做到不重不漏。第二,对于在y轴上的点,x=0,我们把它的斜率赋值为INF,而不是-INF,避免情况遗漏。


代码(新学了重载运算符,作下笔记。。。)
#include <cstdio>
#include <algorithm>
using namespace std;
const double INF = 1<<30;
int T, n;
int s1, s2;
long long ans;

struct Node
{
    double ang;
    int x, val;
    bool operator <(const Node&p)const//重载运算符 <
    {
        return ang<p.ang;
    }
}nd[50005];

/*
struct Node
{
    double ang;
    int x, val;
}nd[50005];

bool cmp(Node a, Node b)
{
    return a.ang < b.ang;
}
*/

int main()
{
    scanf ("%d",&T);
    while (T--)
    {
        scanf ("%d",&n);
        int a, b, v;
        s1 = s2 = 0;
        for (int i=0; i<n; ++i)
        {
            scanf ("%d %d %d",&a,&b,&v);
            nd[i].x = a;
            nd[i].val = v;
            if (a == 0)
                nd[i].ang = INF;//(y<0? -INF: INF);
            else
                nd[i].ang = (double)b/(double)a;
            if (a >= 0)
                s1 += v;
            else
                s2 += v;
        }
        ans = s1*s2;
        sort(nd, nd+n);
        //sort(nd, nd+n, cmp);
        for (int i=0; i<n; ++i)
        {
            if (nd[i].x >= 0)
            {
                s1 -= nd[i].val;
                s2 += nd[i].val;
            }
            else
            {
                s1 += nd[i].val;
                s2 -= nd[i].val;
            }
            ans = max(ans,(long long)s1*s2);
        }
        printf ("%lld\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值