zoukankan      html  css  js  c++  java
  • HDU 6127 Hard challenge(扫描线)

    http://acm.hdu.edu.cn/showproblem.php?pid=6127

    题意:

    有n个点,每个点有一个$(x,y)$坐标和一个权值,任意两点之间都有连线,并且连线的权值为两个顶点的。现在画一条直线,求穿过的直线的权值和最大为多少。

     

    思路:

    直线将这些点分成了两个部分,然后你可以发现这两个部分之间所有直线的权值和为他们各部分的权值和的乘积。然后我们将所有点按极角排序,预处理一个前缀和,然后用扫描线扫描一圈即可。

    我的做法是每次扫描一下点的个数,然后利用前缀和去计算。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<sstream>
     6 #include<vector>
     7 #include<stack>
     8 #include<queue>
     9 #include<cmath>
    10 #include<map>
    11 #include<set>
    12 using namespace std;
    13 
    14 #define MAXN 50005
    15 #define LL long long
    16 
    17 struct Point
    18 {
    19     LL x,y;
    20     int v;
    21     double rad;
    22     bool operator < (const Point&rhs) const
    23     {
    24         return rad < rhs.rad;
    25     }
    26 }p[MAXN];
    27 
    28 LL sum[MAXN];
    29 
    30 bool left(Point a, Point b)
    31 {
    32      return (LL)a.x*b.y - (LL)a.y*b.x >= 0;
    33 }
    34 
    35 int main()
    36 {
    37     int n,m,T;
    38     //freopen("in.txt","r",stdin);
    39     scanf("%d",&T);
    40     while(T--)
    41     {
    42         scanf("%d",&n);
    43         for(int i=0;i<n;i++)
    44         {
    45             scanf("%I64d%I64d%d",&p[i].x,&p[i].y,&p[i].v);
    46             p[i].rad = atan2(p[i].y, p[i].x);
    47         }
    48         sort(p,p+n);
    49         sum[0]=p[0].v;
    50         for(int i=1;i<n;i++)  sum[i]=sum[i-1]+p[i].v;
    51 
    52         LL ans=0;
    53         LL  L = 0, R = 0, cnt=0;
    54         while (L < n)   //每个点都尝试与原点成为分割线
    55         {
    56             if (R == L)  { R = (R + 1) % n; cnt++; }  //空区域,数量+1,后面还会减去的
    57             while (R != L && left(p[L], p[R]))   //R不等于L并且在180度之内
    58             {
    59                 R = (R + 1) % n;
    60                 cnt++;
    61             }
    62 
    63             cnt--; //分隔线旋转,原本在分隔线上的点到了右边,所以要减去
    64                    //可以理解为将该点分在分隔线的下方
    65 
    66             LL t1,t2;
    67             int num=L+cnt;
    68             if(num<n)
    69             {
    70                 t1=sum[num]-sum[L];
    71                 t2=sum[n-1]-t1;
    72                 ans=max(ans,t1*t2);
    73             }
    74             else
    75             {
    76                 t1=sum[n-1]-sum[L]+sum[num-(n-1)-1];
    77                 t2=sum[n-1]-t1;
    78                 ans=max(ans,t1*t2);
    79             }
    80             L++;   //分隔线旋转
    81         }
    82         printf("%I64d
    ",ans);
    83     }
    84     return 0;
    85 }
  • 相关阅读:
    UVA12125 March of the Penguins (最大流+拆点)
    UVA 1317 Concert Hall Scheduling(最小费用最大流)
    UVA10249 The Grand Dinner(最大流)
    UVA1349 Optimal Bus Route Design(KM最佳完美匹配)
    UVA1212 Duopoly(最大流最小割)
    UVA1395 Slim Span(kruskal)
    UVA1045 The Great Wall Game(二分图最佳匹配)
    UVA12168 Cat vs. Dog( 二分图最大独立集)
    hdu3488Tour(KM最佳完美匹配)
    UVA1345 Jamie's Contact Groups(最大流+二分)
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7367728.html
Copyright © 2011-2022 走看看