Space Ant(极角排序)

Space Ant

http://poj.org/problem?id=1696

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 5371   Accepted: 3343

Description

The most exciting space discovery occurred at the end of the 20th century. In 1999, scientists traced down an ant-like creature in the planet Y1999 and called it M11. It has only one eye on the left side of its head and just three feet all on the right side of its body and suffers from three walking limitations: 
  1. It can not turn right due to its special body structure. 
  2. It leaves a red path while walking. 
  3. It hates to pass over a previously red colored path, and never does that.

The pictures transmitted by the Discovery space ship depicts that plants in the Y1999 grow in special points on the planet. Analysis of several thousands of the pictures have resulted in discovering a magic coordinate system governing the grow points of the plants. In this coordinate system with x and y axes, no two plants share the same x or y
An M11 needs to eat exactly one plant in each day to stay alive. When it eats one plant, it remains there for the rest of the day with no move. Next day, it looks for another plant to go there and eat it. If it can not reach any other plant it dies by the end of the day. Notice that it can reach a plant in any distance. 
The problem is to find a path for an M11 to let it live longest. 
Input is a set of (x, y) coordinates of plants. Suppose A with the coordinates (xA, yA) is the plant with the least y-coordinate. M11 starts from point (0,yA) heading towards plant A. Notice that the solution path should not cross itself and all of the turns should be counter-clockwise. Also note that the solution may visit more than two plants located on a same straight line. 

Input

The first line of the input is M, the number of test cases to be solved (1 <= M <= 10). For each test case, the first line is N, the number of plants in that test case (1 <= N <= 50), followed by N lines for each plant data. Each plant data consists of three integers: the first number is the unique plant index (1..N), followed by two positive integers x and y representing the coordinates of the plant. Plants are sorted by the increasing order on their indices in the input file. Suppose that the values of coordinates are at most 100.

Output

Output should have one separate line for the solution of each test case. A solution is the number of plants on the solution path, followed by the indices of visiting plants in the path in the order of their visits.

Sample Input

2
10
1 4 5
2 9 8
3 5 9
4 1 7
5 3 2
6 6 3
7 10 10
8 8 1
9 2 4
10 7 6
14
1 6 11
2 11 9
3 8 7
4 12 8
5 9 20
6 3 2
7 1 6
8 2 13
9 15 1
10 14 17
11 13 19
12 5 18
13 7 3
14 10 16

Sample Output

10 8 7 3 4 9 5 6 2 1 10
14 9 10 11 5 12 8 7 6 13 4 14 1 3 2

 

找到最左下的点,然后对极角排序即可

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<vector>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<cmath>
  7 using namespace std;
  8 const double eps=1e-8;
  9 const double INF=1e20;
 10 const double PI=acos(-1.0);
 11 const int maxp=1010;
 12 int sgn(double x){
 13     if(fabs(x)<eps) return 0;
 14     if(x<0) return -1;
 15     else return 1;
 16 }
 17 inline double sqr(double x){return x*x;}
 18 struct Point{
 19     int pos;
 20     double x,y;
 21     Point(){}
 22     Point(double _x,double _y){
 23         x=_x;
 24         y=_y;
 25     }
 26     void input(){
 27         scanf("%lf %lf",&x,&y);
 28     }
 29     void output(){
 30         printf("%.2f %.2f\n",x,y);
 31     }
 32     bool operator == (const Point &b)const{
 33         return sgn(x-b.x) == 0 && sgn(y-b.y)== 0;
 34     }
 35     bool operator < (const Point &b)const{
 36         return sgn(x-b.x)==0?sgn(y-b.y)<0:x<b.x;
 37     }
 38     Point operator - (const Point &b)const{
 39         return Point(x-b.x,y-b.y);
 40     }
 41     //叉积
 42     double operator ^ (const Point &b)const{
 43         return x*b.y-y*b.x;
 44     }
 45     //点积
 46     double operator * (const Point &b)const{
 47         return x*b.x+y*b.y;
 48     }
 49     //返回长度
 50     double len(){
 51         return hypot(x,y);
 52     }
 53     //返回长度的平方
 54     double len2(){
 55         return x*x+y*y;
 56     }
 57     //返回两点的距离
 58     double distance(Point p){
 59         return hypot(x-p.x,y-p.y);
 60     }
 61     Point operator + (const Point &b)const{
 62         return Point(x+b.x,y+b.y);
 63     }
 64     Point operator * (const double &k)const{
 65         return Point(x*k,y*k);
 66     }
 67     Point operator / (const double &k)const{
 68         return Point(x/k,y/k);
 69     }
 70 
 71     //计算pa和pb的夹角
 72     //就是求这个点看a,b所成的夹角
 73     ///LightOJ1202
 74     double rad(Point a,Point b){
 75         Point p=*this;
 76         return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p)));
 77     }
 78     //化为长度为r的向量
 79     Point trunc(double r){
 80         double l=len();
 81         if(!sgn(l)) return *this;
 82         r/=l;
 83         return Point(x*r,y*r);
 84     }
 85     //逆时针转90度
 86     Point rotleft(){
 87         return Point(-y,x);
 88     }
 89     //顺时针转90度
 90     Point rotright(){
 91         return Point(y,-x);
 92     }
 93     //绕着p点逆时针旋转angle
 94     Point rotate(Point p,double angle){
 95         Point v=(*this) -p;
 96         double c=cos(angle),s=sin(angle);
 97         return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
 98     }
 99 };
100 
101 struct Line{
102     Point s,e;
103     Line(){}
104     Line(Point _s,Point _e){
105         s=_s;
106         e=_e;
107     }
108     bool operator==(Line v){
109         return (s==v.s)&&(e==v.e);
110     }
111     //根据一个点和倾斜角angle确定直线,0<=angle<pi
112     Line(Point p,double angle){
113         s=p;
114         if(sgn(angle-PI/2)==0){
115             e=(s+Point(0,1));
116         }
117         else{
118             e=(s+Point(1,tan(angle)));
119         }
120     }
121     //ax+by+c=0;
122     Line(double a,double b,double c){
123         if(sgn(a)==0){
124             s=Point(0,-c/b);
125             e=Point(1,-c/b);
126         }
127         else if(sgn(b)==0){
128             s=Point(-c/a,0);
129             e=Point(-c/a,1);
130         }
131         else{
132             s=Point(0,-c/b);
133             e=Point(1,(-c-a)/b);
134         }
135     }
136     void input(){
137         s.input();
138         e.input();
139     }
140     void adjust(){
141         if(e<s) swap(s,e);
142     }
143     //求线段长度
144     double length(){
145         return s.distance(e);
146     }
147     //返回直线倾斜角 0<=angle<pi
148     double angle(){
149         double k=atan2(e.y-s.y,e.x-s.x);
150         if(sgn(k)<0) k+=PI;
151         if(sgn(k-PI)==0) k-=PI;
152         return k;
153     }
154     //点和直线的关系
155     //1 在左侧
156     //2 在右侧
157     //3 在直线上
158     int relation(Point p){
159         int c=sgn((p-s)^(e-s));
160         if(c<0) return 1;
161         else if(c>0) return 2;
162         else return 3;
163     }
164     //点在线段上的判断
165     bool pointonseg(Point p){
166         return sgn((p-s)^(e-s))==0&&sgn((p-s)*(p-e))<=0;
167     }
168     //两向量平行(对应直线平行或重合)
169     bool parallel(Line v){
170         return sgn((e-s)^(v.e-v.s))==0;
171     }
172     //两线段相交判断
173     //2 规范相交
174     //1 非规范相交
175     //0 不相交
176     int segcrossseg(Line v){
177         int d1=sgn((e-s)^(v.s-s));
178         int d2=sgn((e-s)^(v.e-s));
179         int d3=sgn((v.e-v.s)^(s-v.s));
180         int d4=sgn((v.e-v.s)^(e-v.s));
181         if((d1^d2)==-2&&(d3^d4)==-2) return 2;
182         return (d1==0&&sgn((v.s-s)*(v.s-e))<=0||
183                 d2==0&&sgn((v.e-s)*(v.e-e))<=0||
184                 d3==0&&sgn((s-v.s)*(s-v.e))<=0||
185                 d4==0&&sgn((e-v.s)*(e-v.e))<=0);
186     }
187     //直线和线段相交判断
188     //-*this line -v seg
189     //2 规范相交
190     //1 非规范相交
191     //0 不相交
192     int linecrossseg(Line v){
193         int d1=sgn((e-s)^(v.s-s));
194         int d2=sgn((e-s)^(v.e-s));
195         if((d1^d2)==-2) return 2;
196         return (d1==0||d2==0);
197     }
198     //两直线关系
199     //0 平行
200     //1 重合
201     //2 相交
202     int linecrossline(Line v){
203         if((*this).parallel(v))
204             return v.relation(s)==3;
205         return 2;
206     }
207     //求两直线的交点
208     //要保证两直线不平行或重合
209     Point crosspoint(Line v){
210         double a1=(v.e-v.s)^(s-v.s);
211         double a2=(v.e-v.s)^(e-v.s);
212         return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
213     }
214     //点到直线的距离
215     double dispointtoline(Point p){
216         return fabs((p-s)^(e-s))/length();
217     }
218     //点到线段的距离
219     double dispointtoseg(Point p){
220         if(sgn((p-s)*(e-s))<0||sgn((p-e)*(s-e))<0)
221             return min(p.distance(s),p.distance(e));
222         return dispointtoline(p);
223     }
224     //返回线段到线段的距离
225     //前提是两线段不相交,相交距离就是0了
226     double dissegtoseg(Line v){
227         return min(min(dispointtoseg(v.s),dispointtoseg(v.e)),min(v.dispointtoseg(s),v.dispointtoseg(e)));
228     }
229     //返回点P在直线上的投影
230     Point lineprog(Point p){
231         return s+(((e-s)*((e-s)*(p-s)))/((e-s).len2()));
232     }
233     //返回点P关于直线的对称点
234     Point symmetrypoint(Point p){
235         Point q=lineprog(p);
236         return Point(2*q.x-p.x,2*q.y-p.y);
237     }
238 };
239 
240 Line L[100005];
241 int book[100005];
242 int n;
243 
244 bool Check(Line a,Line b){
245     if(sgn((a.s-a.e)^(b.s-a.e))*sgn((a.s-a.e)^(b.e-a.e))>0) return false;
246     if(sgn((b.s-b.e)^(a.s-b.e))*sgn((b.s-b.e)^(a.e-b.e))>0) return false;
247     if(sgn(max(a.s.x,a.e.x)-min(b.s.x,b.e.x))>=0&&sgn(max(b.s.x,b.e.x)-min(a.s.x,a.e.x))>=0
248      &&sgn(max(a.s.y,a.e.y)-min(b.s.y,b.e.y))>=0&&sgn(max(b.s.y,b.e.y)-min(a.s.y,a.e.y))>=0)
249         return true;
250     else return false;
251 }
252 
253 Point p[105];
254 int pos;
255 
256 double dist(Point a,Point b){
257     return (b-a)*(b-a);
258 }
259 
260 bool cmp(Point a,Point b){
261     double tmp=(a-p[pos])^(b-p[pos]);
262     if(sgn(tmp)>0){
263         return true;
264     }
265     else if(sgn(tmp)<0){
266         return false;
267     }
268     else return dist(p[pos],a)<dist(p[pos],b);
269 }
270 
271 int main(){
272     int T;
273     std::ios::sync_with_stdio(false);
274     cin>>T;
275     while(T--){
276         int n;
277         cin>>n;
278         pos=1;
279         for(int i=1;i<=n;i++){
280             cin>>p[i].pos>>p[i].x>>p[i].y;
281         }
282         Point tmp=p[1];
283         int pp=1;
284         for(int i=2;i<=n;i++){
285             if((p[i].y<tmp.y)||(p[i].y==tmp.y&&p[i].x<tmp.x)){
286                 tmp=p[i];
287                 pp=i;
288             }
289         }
290         swap(p[pp],p[1]);
291         vector<int>ve;
292         ve.push_back(p[1].pos);
293         for(int i=1;i<n;i++){
294             sort(p+pos,p+n+1,cmp);
295             pos++;
296             ve.push_back(p[pos].pos);
297         }
298         cout<<n;
299         for(int i=0;i<ve.size();i++){
300             cout<<" "<<ve[i];
301         }
302         cout<<endl;
303     }
304     return 0;
305 }
View Code

 

posted on 2018-11-14 21:57  Fighting_sh  阅读(518)  评论(0编辑  收藏  举报

导航