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);
}
}