poj 1696 Space Ant(极角排序)

Space Ant

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 3661   Accepted: 2281

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

Source

Tehran 1999

题意:一种生物只能逆时针走,且路线不与走过的路线交叉~

现在有好多植物,这种生物一次会走到一棵植物上,直到按照前面的行动规则没有植物可以走,结束。

那么问最长的依次拜访点的路线是怎么样~

恩,不废话了。

输入:t组数据,每组n个点,接下来每行三个数据分别代表 点的编号,点的横坐标,点的纵坐标(点为植物)。

输出:n个点,以及排过序的点的编号,

第一道极角排序~

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <math.h>
 7 #include <algorithm>
 8 #include <cctype>
 9 #include <string>
10 #include <map>
11 #include <set>
12 #define ll long long
13 using namespace std;
14
15 const double eps = 1e-8;
16 int sgn(double x)
17 {
18     if(fabs(x) < eps)return 0;
19     if(x < 0)return -1;
20     else return 1;
21 }
22 struct Point
23 {
24     double x,y;
25     int th;
26     Point() {}
27     Point(double _x,double _y)
28     {
29         x = _x;
30         y = _y;
31     }
32     Point operator -(const Point &b)const
33     {
34         return Point(x - b.x,y - b.y);
35     }
36     double operator ^(const Point &b)const
37     {
38         return x*b.y - y*b.x;
39     }
40     double  operator *(const Point &b)const
41     {
42         return x*b.x + y*b.y;
43     }
44 };
45
46 double dist(Point a,Point b)
47 {
48     return sqrt((a-b)*(a-b));
49 }
50 int pos;
51 Point p[105];
52 bool cmp(Point a,Point b)
53 {
54     double tmp = (a - p[pos])^(b - p[pos]);//叉乘判断方向
55     if(sgn(tmp) == 0) return dist(a,p[pos]) < dist(b,p[pos]);//叉乘结果相同,则让距离远的优先在前面
56     else if(sgn(tmp) < 0) return false;//刚好为逆时针,不交换
57     else return true;//否则交换
58 }
59
60 int main(void)
61 {
62     int t;
63     scanf("%d",&t);
64     while(t--)
65     {
66         int n;
67         scanf("%d",&n);
68         for(int i = 0; i < n; i++)
69         {
70             scanf("%d %lf %lf",&p[i].th,&p[i].x,&p[i].y);
71             if( p[i].y < p[0].y || (p[i].y == p[0].y && p[i].x < p[0].x) )
72                 swap(p[0],p[i]);//找到最左下端的点
73         }
74         pos = 0;
75         for(int i = 0 ; i < n; i++)
76         {
77             sort(p+i,p+n,cmp);//每次都找出未排序中最外围的点
78             pos++;
79         }
80         printf("%d",n);
81         for(int i = 0; i < n; i++)
82             printf(" %d",p[i].th);
83         printf("\n");
84     }
85     return 0;
86 }

ps:奉上几种极角排序的方法,虽然还没有用过~可以去看看 poj 2007

介绍几种极角排序:

1.利用叉积的正负来作cmp.(即是按逆时针排序).此题就是用这种方法

1 bool cmp(const point &a, const point &b)//逆时针排序
2 {
3     point origin;
4     origin.x = origin.y = 0;
5     return cross(origin,b,origin,a) < 0;
6 }

2.利用complex的内建函数。

 1 #include<complex>
 2 #define x real()
 3 #define y imag()
 4 #include<algorithm>
 5 using namespace std;
 6
 7 bool cmp(const Point& p1, const Point& p2)
 8 {
 9     return arg(p1) < arg(p2);
10 }

3.利用arctan计算极角大小。(范围『-180,180』)

1 bool cmp(const Point& p1, const Point& p2)
2 {
3     return atan2(p1.y, p1.x) < atan2(p2.y, p2.x);
4 }

4.利用象限加上极角,叉积。

 1 bool cmp(const point &a, const point &b)//先按象限排序,再按极角排序,再按远近排序
 2 {
 3     if (a.y == 0 && b.y == 0 && a.x*b.x <= 0)return a.x>b.x;
 4     if (a.y == 0 && a.x >= 0 && b.y != 0)return true;
 5     if (b.y == 0 && b.x >= 0 && a.y != 0)return false;
 6     if (b.y*a.y <= 0)return a.y>b.y;
 7     point one;
 8     one.y = one.x = 0;
 9     return cross(one,a,one,b) > 0 || (cross(one,a,one,b) == 0 && a.x < b.x);
10 }
时间: 2024-08-11 18:48:42

poj 1696 Space Ant(极角排序)的相关文章

POJ 1696 Space Ant (极角排序)

题目链接 Space Ant Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3219   Accepted: 2059 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 plane

poj 1696 Space Ant (极角排序)

链接:http://poj.org/problem?id=1696 Space Ant Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3077   Accepted: 1965 Description The most exciting space discovery occurred at the end of the 20th century. In 1999, scientists traced down an a

POJ 1696 Space Ant(点积的应用)

Space Ant 大意:有一只蚂蚁,每次都只向当前方向的左边走,问蚂蚁走遍所有的点的顺序输出.开始的点是纵坐标最小的那个点,开始的方向是开始点的x轴正方向. 思路:从开始点开始,每次找剩下的点中与当前方向所形成的夹角最小的点,为下一个要走的点(好像就是犄角排序,我不是很会),夹角就是用点积除以两个向量的距离,求一下acos值. 之前一直用叉积做,做了好久样例都没过,发现用错了... 题目挺好的,有助于理解点积与叉积 1 struct Point{ 2 double x, y; 3 int id

POJ 1696 Space Ant 【极角排序】

题意:平面上有n个点,一只蚂蚁从最左下角的点出发,只能往逆时针方向走,走过的路线不能交叉,问最多能经过多少个点. 思路:每次都尽量往最外边走,每选取一个点后对剩余的点进行极角排序.(n个点必定能走完,这是凸包的性质决定的) #include<stdio.h> #include<string.h> #include<math.h> #include<iostream> #include<algorithm> using namespace std;

POJ 1696 Space Ant 卷包裹法

Space Ant Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3316   Accepted: 2118 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 Y19

POJ 1696 Space Ant

极角排序 每次选择一个最外围的没选过的点,选择的时候需要利用极角排序进行选择 #include<cstdio> #include<cstring> #include<vector> #include<cmath> #include<queue> #include<list> #include<algorithm> using namespace std; const double eps=1e-8; struct poin

poj 1696 Space Ant(模拟+叉积)

Space Ant Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3840   Accepted: 2397 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 Y19

POJ 1696 Space Ant 计算几何 叉积的应用

题目大意:平面内有一些点,我们要通过一些方式来走遍这所有的点,要求一个点只能走一次,只能向左转而不能向右转.求遍历这些点的顺序. 思路:数据范围是可以怎么搞都0ms的(n<=50,case<=100),所以只要有思路就可以了. 只能左转,想想好像有点像凸包啊.但是这个题要遍历所有的点,所以就把已经走过的点删掉,然后像凸包一样的往前走,每次找一个没走过的极角最小的点走,然后把它标记上.最后都走完就全部遍历完了. CODE: #include <cmath> #include <

POJ 1696 Space Ant --枚举,模拟,贪心,几何

题意: 有很多点,从最右下角的点开始走起,初始方向水平向右,然后以后每步只能向左边走,问最多能走多少个点. 解法: 贪心的搞的话,肯定每次选左边的与它夹角最小的点,然后走过去. 然后就是相当于模拟地去选点,然后计数,然后走过去.这题就这么搞定了. 我这里用了set和vector. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include &