无论点怎么分布,总有一条路径能使ant经过所有的点。
方法1:
第一次选坐标y值最小的坐标为起始点 也是当前停留点,然后 以当前点为参照,对之后的几个点按级角(斜率)从小到大排序,取极角最小的点,然后继续重复操作,直到所有点取完为止。
View Code
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; #define inf 1<<29 struct point { int num, x, y; }p[33]; point tmp; int n; int cross(point o, point a, point b) { return (a.x - o.x)*(b.y - o.y) - (a.y - o.y)*(b.x - o.x); } double ff(int x) { return x*x*1.0; } double dis(point a, point b) { return sqrt(ff(a.x - b.x) + ff(a.y - b.y)); } bool cmp1(point a, point b) { return a.y < b.y; } bool cmp2(point a, point b) { int ret = cross(tmp, a, b); if(ret > 0)return 1; else if(ret < 0)return 0; return dis(a, tmp) > dis(b, tmp); } int main() { int cas, i, j; scanf("%d",&cas); while(cas--) { scanf("%d",&n); for(i=0;i<n;i++) scanf("%d%d%d",&p[i].num, &p[i].x, &p[i].y); sort(p, p+n, cmp1); tmp = p[0]; printf("%d %d",n, p[0].num); for(i=1;i<n;i++) { sort(p+i, p+n, cmp2); tmp = p[i]; printf(" %d",p[i].num); } puts(""); } return 0; }
方法2:
凸包1:卷包裹算法。
卷包裹算法:http://www.cnblogs.com/ACMan/archive/2012/08/17/2644644.html
View Code
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; #define eps 1e-8 #define inf 1<<29 struct point { double x, y; }p[101]; double det(double x1, double y1, double x2, double y2) { return x1 * y2 - x2 * y1; } double cross(point o, point a, point b) { return det(a.x - o.x, a.y - o.y, b.x - o.x, b.y - o.y); } double f(double x) { return x * x; } double dis(point a, point b) { return sqrt( f(a.x - b.x) + f(a.y - b.y) ); } int n; int num; int conbag[101]; //储存凸包顶点顺序 bool vis[101]; int main() { int cas, i, j; scanf("%d", &cas); while(cas--) { scanf("%d", &n); double min_y = inf; int fi = 0; //取最左下方的点 for(i = 1; i <= n; i++) { scanf("%*d%lf%lf", &p[i].x, &p[i].y ); if(min_y > p[i].y) { min_y = p[i].y; fi = i; } else if(min_y == p[i].y && p[i].x < p[fi].x) fi = i; } memset(vis, false, sizeof(vis)); int num = 1; vis[fi] = 1; conbag[num] = fi; while(1) { int k; int s = conbag[num]; for(i = 1; i <= n; i++) if(!vis[i]) { k = i; break; } for(i = 1; i <= n; i++) if(k != i && !vis[i]) { double tmp = cross(p[s], p[k], p[i]); if(tmp < 0) k = i; else if(tmp == 0) if( dis(p[s], p[i]) < dis(p[s], p[k]) ) k = i; } vis[k] = 1; conbag[++num] = k; if(num == n - 1)break; } printf("%d ", n); fi = -1; for(i = 1; i <= num; i++) { printf("%d ", conbag[i]); if(!vis[i]) fi = i; } if(fi == -1) printf("%d\n", n); else printf("%d\n", fi); } return 0; }