暑假牛客多校赛第三场H.Magic Line(简单计算几何)

H.Magic Line(简单计算几何)

传送门

题目大意:

给你n个点,让你用一条直线将它们均匀分开,且点不能在直线上,点的坐标只能在-2000<=x,y<=2000内。
直线用两个定点表示

思路:

给点排个序,然后只要有一条直线经过中间两个点的中点且不经过其他点即可。中点的x和y要么含小数0.5,要么是整数。
(注意:若排序时y是递增的,直线的斜率要大于0,若排序时y是递减的,直线的斜率要小于0)

本来这道题不想写题解的,但是比赛中遇到了一个问题就是正负数的向上向下取整。。。
为了避免乱套,还是写一篇博客来提醒一下自己。

对于正负数

  • 向上取整:ceil(x);
  • 向下取整:floor(x);

不用什么+1-1,如果要去最近的两个整数点,最好的办法就是分该数原来是整数和不是整数讨论。

题目ac代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
struct node{
    int x,y;
}point[1005];
 
bool cmp(const node&a,const node&b){
    if(a.x!=b.x)return a.x<b.x;
    else return a.y>b.y;
}
 
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        ll upx,upy,downx,downy;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d %d",&point[i].x,&point[i].y);
        }
        sort(point+1,point+n+1,cmp);
        double x=double(point[n/2].x+point[n/2+1].x)/2.0;
        double y=double(point[n/2].y+point[n/2+1].y)/2.0;
        //cout<<x<<" "<<y<<endl;
        if(point[n/2].x%2==point[n/2+1].x%2){
                upx=(point[n/2].x+point[n/2+1].x)/2+1;
                downx=(point[n/2].x+point[n/2+1].x)/2-1;
        }
        else{
            if(x>=0){
            upx=floor(x+1);
            downx=ceil(x-1);
            }
            else{
             downx=floor(x);
             upx=ceil(x);
            }
        }
 
        int Y;
        if(point[n/2].y%2!=point[n/2+1].y%2){
        Y=floor(y);
        }
        else{
        Y=(point[n/2].y+point[n/2+1].y)/2;
        }
 
        //cout<<Y<<endl;
        if(point[n/2].y%2!=point[n/2+1].y%2){
        upy=(ll)2e8+Y+1;
        downy=(ll)-2e8+Y;
        }
        else{
        upy=ll(2e8)+Y;
        downy=ll(-2e8)+Y;
        }
 
        //printf("%.2f %.2f\n",(upx+downx)/2.0,(upy+downy)/2.0);
        if(upx<downx) swap(upx,upy);
         printf("%lld %lld %lld %lld\n",upx,upy,downx,downy);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值