题目描述
There are always some problems that seem simple but is difficult to solve.
Z Y B ZYB ZYB got N N 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 T T ( 1 ≤ T ≤ 10000 1\leq T \leq 10000 1≤T≤10000) indicating the number of cases.
For each case, the first line of the input contains a single even integer N N N ( 2 ≤ N ≤ 1000 2\leq N\leq 1000 2≤N≤1000), the number of points. The following N N N lines each contains two integers x i , y i x_i,y_i xi,yi ( ∣ x i , y i ∣ ≤ 1000 \mid x_i,y_i\mid \leq 1000 ∣xi,yi∣≤1000), denoting the x x x-coordinate and the y y y-coordinate of the i i i-th point.
It is guaranteed that the sum of N N N over all cases does not exceed 2 × 1 0 5 2 \times 10^5 2×105.
题目大意
在笛卡尔坐标系中有 N N N个点,去找到某一条直线将这 N N N个点划分为两个部分,每个部分点的个数相同,同时该直线不能经过坐标系中任意一个点,找到该直线中的两个整数点。
解题思路
坐标系中的每个点按照
x
x
x从小到大排序,若
x
x
x相同则按照
y
y
y从小到大进行排序,找到中间点
(
x
,
y
)
(x,y)
(x,y),过中间点垂直于
x
x
x轴的直线
l
l
l能够将坐标系中的点划分为近似相等的两个部分,由中间点坐标可以得到两个点,
a
(
x
−
1
,
y
+
1
0
8
)
a(x-1,y+10^8)
a(x−1,y+108),
b
(
x
+
1
,
y
−
1
0
8
)
b(x+1,y-10^8)
b(x+1,y−108),(至于为什么加
1
0
8
10^8
108,因为必须要加一个特别大的数才能让垂直的直线变化尽可能的小,而题目中告诉
m
a
x
(
x
i
)
,
m
a
x
(
y
i
)
max(x_i),max(y_i)
max(xi),max(yi)为
1000
1000
1000,而最后答案不能超过
1
0
9
10^9
109,能加的最大数即为
1
0
8
1 0^8
108)过这两点的直线得到过中点
(
x
,
y
)
(x,y)
(x,y)且近似为
l
l
l的一条直线,然后
a
a
a点的
y
y
y坐标+1,将直线稍微向上倾斜,点E划分到左边部分,由此得到的直线可以将坐标系中的点划分为两个部分。
AC代码
#include <bits/stdc++.h>
const int Max_N=1e3+100;
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
struct Num
{
int x,y;
};
bool cmp(Num a,Num b)
{
if(a.x!=b.x)
return a.x<b.x;
return a.y<b.y;
}
Num num[Max_N];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>num[i].x>>num[i].y;
}
sort(num,num+n,cmp);
ll x1=num[n/2-1].x;
ll y1=num[n/2-1].y;
cout<<x1-1<<" "<<(ll)(y1+100000000+1)<<" "<<x1+1<<" "<<(ll)(y1-100000000)<<endl;
}
return 0;
}
总结
在最开始的时候把这道题想的太复杂了,由此陷入了思维泥潭。该题虽然是在二维坐标中,但在划分为两个部分的时候思路只需考虑一维的情况,然后稍微扩展一点便可。