• 2019牛客暑期多校训练营(第十场) G Road Construction(计算几何、思维)


    https://ac.nowcoder.com/acm/contest/890/G

    题意

    平面上有偶数个点,现在你要找出一条直线将这些点隔开成数量相同的两部分,直线不能穿过任何一点

    问离直线最近的点离直线的距离最大是多少?

    题解

    必须知道一个结论:

    这条最优的直线一定是与某两点连线平行或垂直。

    那么我们可以枚举直线斜率n^2,然后求出所有点到这条直线的距离并排序nlogn,

    那么中间的两个的差值除以2就是答案。

    总时间复杂度n^3logn,n最大为300可以接受。

    举个例子,如图(其实就是第一个样例),我们要把A,B,C,D,E,F分开,假设我们已经枚举到平行BD的直线AG,

    那么答案为(BM-CH)/2。

    代码很好写

     1 #define bug(x) cout<<#x<<" is "<<x<<endl
     2 #define IO std::ios::sync_with_stdio(0)
     3 #include <bits/stdc++.h>
     4 #define iter ::iterator
     5 #define pa pair<int,ll>
     6 using namespace  std;
     7 #define ll long long
     8 #define mk make_pair
     9 #define pb push_back
    10 #define se second
    11 #define fi first
    12 ll mod=998244353;
    13 const int N=1e5+5;
    14 int n;
    15 struct node{
    16     double x,y;
    17 }p[N];
    18 double ans=0;
    19 double d[N];
    20 void cal(double k){
    21     for(int i=1;i<=n;i++){
    22         d[i]=(k*p[i].x-p[i].y)/sqrt(1+k*k);
    23     }
    24     sort(d+1,d+1+n);
    25     double res=(d[n/2+1]-d[n/2])/2;
    26     ans=max(ans,res);
    27 }
    28 int main(){
    29     scanf("%d",&n);
    30     for(int i=1;i<=n;i++){
    31         scanf("%lf%lf",&p[i].x,&p[i].y);
    32     }
    33     for(int i=1;i<=n;i++){
    34         for(int j=1;j<i;j++){
    35             double k=(p[i].y-p[j].y)/(p[i].x-p[j].x);
    36             cal(k);
    37             k=-1/k;
    38             cal(k);
    39         }
    40     }
    41     printf("%.10lf
    ",ans);
    42 }
  • 相关阅读:
    Android中传感器的基本概念
    Android攻城狮 multi-touch多点触摸
    Android攻城狮SurfaceView
    Android攻城狮Tab类型
    Android攻城狮使用SubMenu创建子菜单
    Android攻城狮认识ContextMenu
    Android攻城狮OptionsMenu
    Android攻城狮Notification实现状态通知栏
    虹软人脸识别SDK(java+linux/window)
    人脸识别ArcFace C#DEMO 开发应用全过程
  • 原文地址:https://www.cnblogs.com/ccsu-kid/p/11380666.html
Copyright © 2020-2023  润新知