HDU 6127 Hard challenge

来源:互联网 发布:无法访问家庭网络共享 编辑:程序博客网 时间:2024/06/11 13:54

题目链接

题目意思

平面上有(n)个点,已知每个点的坐标为((x,y)),以及该点的权值为(val),任意两点之间可以连接成一条不经过原点的边,该边的权值是两个端点的权值的乘积。现在要求画一条经过原点的直线,定义这条直线的权值为这条直线穿过的所有线段的值的和,问权值的最大值。

解题思路

我们将所有的点按照极角排序,分别散落在y轴的左右两侧,y轴左端的点的和为suml,右端的点的和为sumr,则权值和为suml*sumr 。我们先以y轴为起始点,不断偏移,更新suml,sumr。以便刷新ans,找到最大的权值。因为两点不经过原点,所以只能偏移一个点。

代码部分

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>typedef long long ll;using namespace std;#define eps 1e-9#define maxn 200005struct node{    double x,y,ang;///横纵坐标和极角    int val;///点的权值}p[maxn];bool cmp(node a,node b)///极角从小到大排序{    return a.ang<b.ang;}int n,T;ll suml,sumr,ans;void work(){    scanf("%d",&n);    for(int i=1; i<=n; i++)    {        scanf("%lf%lf%d",&p[i].x,&p[i].y,&p[i].val);        p[i].ang=atan(p[i].y/p[i].x);///极角的计算    }    sort(p+1,p+n+1,cmp);    suml=sumr=ans=0;    for(int i=1; i<=n; i++)    {        if(p[i].x>eps)            suml+=p[i].val;        else            sumr+=p[i].val;    }    ans=suml*sumr;    for(int i=1; i<=n; i++)///以y轴不断偏移    {        if(p[i].x>0)            suml-=p[i].val,sumr+=p[i].val;        else            suml+=p[i].val,sumr-=p[i].val;        ans=max(ans,suml*sumr);    }    printf("%lld\n",ans);}int main(){    scanf("%d",&T);    while(T--)    {        work();    }    return 0;}
原创粉丝点击