首先发出题目链接:
链接:https://ac.nowcoder.com/acm/contest/883/H
来源:牛客网
涉及:思维,简单平面几何
点击这里回到2019牛客暑期多校训练营解题—目录贴
题目如下:
此题的方法有好多种,我就讲讲我的方法
首先对所有点按照先将 从小到大,后将 从小到大排序。
那么这条直线可以经过第 和第 个点的中间。假设第 个点的座标为 ,第 个点的座标为
那么这两个点可能满足下面的位置关系:
1.两个点不在同一垂线上,即 。
由于排序之后,一半的点的 值肯定比点 的 值要小,另一半的点的 值肯定比 的 值要大,所以完全可以按照上图一样,在这两个点的中点处画一条垂直线。
但是这条直线可能不经过任何整数座标点,所以需要将这条直线稍微倾斜,如下图
由于所有点的 值 值都小于1000,而上面直线的经过的两个整点在 的区域外面,且在区域内不经过任何整点,直线也刚好经过 和 的中点,把平面内的点分成了等量的两部分。
if(a.x!=b.x) printf("%d 999000000 %d %d\n",a.x,b.x,(a.y+b.y)-999000000);//a,b分别指Point[n/2]与Point[n/2+1]
当然把垂直线向左倾斜和向右倾斜都是同样的效果。上图是把垂直线向左倾斜的结果。
2.两个点恰好在同一垂线上,即
不妨令
对于这种情况,可以做一条直线,如下图
但是注意,这条直线只能向左倾斜,不能向右倾斜。因为在排序的时候是按照当 相同时, 从小到大排序的,所以可能存在某些点的 值与这两个点的 值相同,但是高于点 ,这些点要被归纳于直线右边的点,才能使得直线左右两半部分的点数量相同。
printf("%d 999000000 %d %d\n",a.x-1,b.x+1,(a.y+b.y)-999000000);
代码如下:
#include <iostream>
#include <algorithm>
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int,int> P;//P的平面上的点类型
int t,n;//题目所给变量
bool comp(P a,P b){
if(a.x!=b.x) return a.x<b.x;
else return a.y<b.y;
}
int main(){
cin>>t;
while(t--){
scanf("%d",&n);
P point[1005];
int i;
for(i=1;i<=n;i++){
scanf("%d%d",&point[i].x,&point[i].y);
}
sort(point+1,point+n+1,comp);//对所有点按x从小到大,y从小到大排序
P a=point[n/2],b=point[n/2+1];
if(a.x!=b.x) printf("%d 999000000 %d %d\n",a.x,b.x,(a.y+b.y)-999000000);//点在同一垂线上
else printf("%d 999000000 %d %d\n",a.x-1,b.x+1,(a.y+b.y)-999000000); //点不在同一垂线上
}
return 0;
}