zoukankan      html  css  js  c++  java
  • 【牛客网多校】19-7-25-H题 Magic Line

    链接:https://ac.nowcoder.com/acm/contest/883/H
    来源:牛客网

    • 题目描述

    There are always some problems that seem simple but is difficult to solve.

    ZYB got  N distinct points on a two-dimensional plane. He wants to draw a magic line so that the points will be divided into two parts, and the number of points in each part is the same. There is also a restriction: this line can not pass through any of the points.

    Help him draw this magic line.

    输入描述:

    There are multiple cases. The first line of the input contains a single integer T (1≤T≤10000), indicating the number of cases. 

    For each case, the first line of the input contains a single even integer N (2≤N≤1000), the number of points. The following $N$ lines each contains two integers xi,yi (∣xi,yi∣≤1000)
    It is guaranteed that the sum of  N over all cases does not exceed 2×105.

    输出描述:

    For each case, print four integers x1,y1,x2,y2 in a line, representing a line passing through (x1,y1) and (x2,y2). Obviously the output must satisfy (x1,y1)≠(x2,y2).

    The absolute value of each coordinate must not exceed 109. It is guaranteed that at least one solution exists. If there are multiple solutions, print any of them.
    示例1

    输入

    1
    4
    0 1
    -1 0
    1 0
    0 -1

    输出

    -1 999000000 1 -999000001
     
    •  题意

        给定平面上一系列的点,求一条以(x1,y1),(x2,y2)两点表示的直线将平面分为包含点数量相等的两部分,其中直线不能穿过任何一点。

     

    • 解题思路

        计算几何问题。

        示例中的坐标不是随便得到的,将x、y中其中一方拉长到在109以内尽可能大的数,能让直线尽可能水平或者竖直,由于坐标都为整数,这样取值可以使得直线不穿过任何一点,为方便我们取尽可能水平,即x绝对值尽可能大。应该先以y升序,x降序将这些点排序,然后取中位数的两点,若这两点不在同一水平线上,则将这两点的x值扩大;若这两点在同一水平线上,则先将这两点的y坐标一上一下错开,再扩大x的值。

     

    • 错误代码

        最开始考虑完整穿过其他点的所有情况,将直线直接取在了中位点上,又为了防止穿过点而将所取点向上下左右错开,直到所取两点不在给出点集合中。但这种情况仅仅是保证了我所取到的点不在点集中,并不能保证他们所连直线是否穿过别的点。

        错误代码如下:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 struct p
     5 {
     6     ll x,y;
     7 }ps[1002];
     8 bool operator <(struct p a,struct p b)
     9 {
    10     if (a.x!=b.x) return a.x<b.x;
    11     else return a.y<b.y;
    12 }
    13 bool operator ==(struct p a,struct p b)
    14 {
    15     return a.x==b.x&&a.y==b.y;
    16 }
    17 bool operator !=(struct p a,struct p b)
    18 {
    19     return a.x!=b.x||a.y!=b.y;
    20 }
    21 set <struct p> points;
    22 bool cmpx(struct p a,struct p b)
    23 {
    24     return a.x<b.x;
    25 }
    26 bool cmpy(struct p a,struct p b)
    27 {
    28     return a.y<b.y;
    29 }
    30 int main()
    31 {
    32     ll t,n;
    33     scanf("%lld",&t);
    34     while(t--){
    35         ll x1,y1,x2,y2;
    36         scanf("%lld",&n);
    37         for (ll i=0;i<n;i++){
    38             scanf("%lld %lld",&ps[i].x,&ps[i].y);
    39             points.insert(ps[i]);
    40         }
    41         sort(ps,ps+n,cmpx);
    42         x1=ps[n/2-1].x;
    43         x2=ps[n/2].x;
    44         sort(ps,ps+n,cmpy);
    45         y1=ps[n/2-1].y;
    46         y2=ps[n/2].y;
    47         struct p p1,p2;
    48         p1.x=x1;p1.y=y2;
    49         p2.x=x2;p2.y=y2;
    50         if (p1==p2){
    51             (p1.x)--;
    52             (p1.y)--;
    53             (p2.x)++;
    54             (p2.y)++;
    55         }
    56         while(points.find(p1)!=points.end()||points.find(p2)!=points.end()){
    57             (p1.x)--;
    58             (p2.x)++;
    59         }
    60         printf("%lld %lld %lld %lld
    ",p1.x,p1.y,p2.x,p2.y);
    61     }
    62     return 0;
    63 }
    • AC代码

        在发现题目的真正做法之后还在另一个地方wa了好多遍,这道题对点的排序也有讲究。先前我们的排序方法是x升序,y升序,但拉长x值的时候是将较大x值向上拉长,较小x值向下拉长。这样选取点的话会造成选取的部分并没有被分开。

        即如果我们选择将较大x值向上拉长,较小x值向下拉长的话,这条直线应该是向右上方倾斜的,将平面分成的是左上和右下的两部分,选取点时也自然应该从下到上,从右到左。

        AC代码如下:

    
    
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 struct p
     5 {
     6     ll x,y;
     7 }ps[1002];
     8 bool cmpx(struct p a,struct p b)
     9 {
    10     return a.x<b.x;
    11 }
    12 bool cmpy(struct p a,struct p b)
    13 {
    14     if(a.y!=b.y) return a.y<b.y;
    15     else return a.x>b.x;
    16 }
    17 int main()
    18 {
    19     ll t,n;
    20     scanf("%lld",&t);
    21     while(t--){
    22         ll x1,y1,x2,y2;
    23         scanf("%lld",&n);
    24         for (ll i=0;i<n;i++){
    25             scanf("%lld %lld",&ps[i].x,&ps[i].y);
    26         }
    27         sort(ps,ps+n,cmpy);
    28         x1=(ps[n/2-1].x);
    29         y1=ps[n/2-1].y;
    30         x2=(ps[n/2].x);
    31         y2=ps[n/2].y;
    32         x1-=999000000;
    33         x2+=999000000;
    34         if (y1==y2) {
    35             y1-=1;
    36             y2+=1;
    37         }
    38         printf("%lld %lld %lld %lld
    ",x1,y1,x2,y2);
    39     }
    40     return 0;
    41 }
    
    
    
    
    
  • 相关阅读:
    Linq技术四:动态Linq技术 -- Linq.Expressions
    74HC595的中文资料
    MessageDigest简单介绍
    gpu显存(全局内存)在使用时数据对齐的问题
    走进windows编程的世界-----windows进程
    Matlab画图-非常具体,非常全面
    php实现 合并表记录(需求是最好的老师)
    php实现求一个数的质数因子
    php课程 4-16 数组自定义函数(php数组->桶)
    jquery-3 jquery选择器
  • 原文地址:https://www.cnblogs.com/sixwater6H2O/p/11247568.html
Copyright © 2011-2022 走看看