【牛客网多校】19-7-25-H题 Magic Line
?
鏈接:https://ac.nowcoder.com/acm/contest/883/H
來源:牛客網
-
題目描述
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\n",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\n",x1,y1,x2,y2); 39 } 40 return 0; 41 }?
轉載于:https://www.cnblogs.com/sixwater6H2O/p/11247568.html
總結
以上是生活随笔為你收集整理的【牛客网多校】19-7-25-H题 Magic Line的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转]25个增强iOS应用程序性能的提示
- 下一篇: SDNU 1481.纪念品分组(水题)