POJ 1696 Space Ant

大致题意:

一只蚂蚁,只会向左转,现在给出平面上很多个点,求解一种走法,
能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉.

输入
输入的第一行是m,要测试的测试用例的数量(1 < = T=10)。对于每一个测试用例,第一行是n,测试用例中的点数量(1 < = n=50),其次是每个点数据的n行。每个植物数据由三个整数组成:第一个数字是编号其次是两个正整数x和y代表植物的坐标。根据输入文件中索引的递增顺序对植物进行排序。假设坐标的值最多为100。
输出
输出应该有一个单独的行,用于每个测试用例的解决方案。一个解决方案是植物在溶液路径上的数量,其次是按照访问顺序在路径上访问植物的索引。

 

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
题解:凸包卷包裹法,用凸包覆盖点可以用这个算法,复杂度O(n^2)
首先,了解一下叉积的性质:l1和l2叉积小于0代表l2在l1右边
根据凸包性质,可以知道,本题必有全解,想得到解,贪心每一次选偏转最小的点,即极角最小。
首先选出y最小的点s,此时没有点在他右边,随便选出一点k
枚举i,比对sk和si线段的叉积,小于0则k=i,依次类推,一层循环得到最靠右极角最小的点s'
同样对s'处理
那么可能会有问题,对于得到的s',因为最靠右,有没有可能朝向右边?
答案是没有
如果对于点s'选中朝右的点,那么s就存在更靠右的值,所以s不会选s'矛盾
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 using namespace std;
 7 double x[1001],y[1001],minn;
 8 bool vis[10001];
 9 int n,cnt;
10 double distan(double x1,double y1,double x2,double y2)
11 {
12     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
13 }
14 double cross(double xx,double yy,double x1,double y1,double x2,double y2)
15 {
16     double dx=x1-xx,dy=y1-yy;
17     double fx=x2-xx,fy=y2-yy;
18     return (dx*fy-fx*dy);
19 }
20 int main()
21 {int T,i,pn,now,nxt,p[1001];
22     cin>>T;
23     while (T--)
24     {
25         memset(vis,0,sizeof(vis));
26         scanf("%d",&n);
27         for (i=1;i<=n;i++)
28         {
29             scanf("%d%lf%lf",&pn,&x[i],&y[i]);
30         }
31         now=0;minn=2e9;
32         for (i=1;i<=n;i++)
33         if (y[i]<minn)
34         {
35             minn=y[i];now=i;
36         }
37         cnt=0;
38         vis[now]=1;
39         p[1]=now;
40         cnt++;
41         while (1)
42         {
43             for (i=1;i<=n;i++)
44             if (vis[i]==0) 
45             {
46              nxt=i;
47              break;
48             }
49             for (i=1;i<=n;i++)
50             if (vis[i]==0&&i!=nxt)
51             {
52                 if (cross(x[now],y[now],x[nxt],y[nxt],x[i],y[i])<0)
53                  nxt=i;
54                  else if (cross(x[now],y[now],x[nxt],y[nxt],x[i],y[i])==0)
55                    if (distan(x[now],y[now],x[i],y[i])<distan(x[now],y[now],x[nxt],y[nxt]))
56                     nxt=i;           
57             }
58             now=nxt;
59             cnt++;
60             p[cnt]=now;
61             vis[now]=1;
62             if (cnt==n) break;
63         }
64         cout<<n<<' ';
65         for (i=1;i<=n;i++)
66         printf("%d ",p[i]);
67         printf("\n");
68     }
69 }

 

 

 

posted @ 2017-08-01 21:52  Z-Y-Y-S  阅读(218)  评论(0编辑  收藏  举报