每次选择向左偏移角度最小的下一个点即可。或者说左边点最多的点。
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <cstdlib> #include <cmath> #include <map> #include <sstream> #include <queue> #include <vector> #define MAXN 100005 #define MAXM 211111 #define eps 1e-8 #define INF 500000001 using namespace std; inline int dblcmp(double d) { if(fabs(d) < eps) return 0; return d > eps ? 1 : -1; } struct point { double x, y; point(){} point(double _x, double _y): x(_x), y(_y) {} void input() { scanf("%lf%lf", &x, &y); } bool operator ==(point a)const { return dblcmp(a.x - x) == 0 && dblcmp(a.y - y) == 0; } point sub(point p) { return point(x - p.x, y - p.y); } double dot(point p) { return x * p.x + y * p.y; } double det(point p) { return x * p.y - y * p.x; } double distance(point p) { return hypot(x - p.x, y - p.y); } }p[555]; int vis[555]; int n; vector<int>ans; int getcount(point a, int id) { int cnt = 0; for(int i = 1; i <= n; i++) { if(vis[i] || id == i) continue; point tmp = p[i].sub(p[id]); if(dblcmp(a.det(tmp)) >= 0) cnt++; } return cnt; } void disable(point a, int id) { for(int i = 1; i <= n; i++) { if(vis[i]) continue; point tmp = p[i].sub(p[id]); if(dblcmp(a.det(tmp)) < 0) vis[i] = 1; } } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d", &n); p[0] = point(0, 0); int pre = 0, now = -1, id; for(int i = 1; i <= n; i++) { scanf("%d", &id); p[i].input(); if(now == -1 || p[i].y < p[now].y) now = i; } memset(vis, 0, sizeof(vis)); ans.clear(); ans.push_back(now); vis[now] = 1; while(true) { int nxt = -1, cnt = 0; for(int i = 1; i <= n; i++) if(!vis[i]) { point x = p[i].sub(p[now]); int num = getcount(x, i); if(num >= cnt) nxt = i, cnt = num; } if(nxt == -1) break; vis[nxt] = 1; point tmp = p[nxt].sub(p[now]); disable(tmp, nxt); ans.push_back(nxt); pre = now; now = nxt; } printf("%d", ans.size()); for(int i = 0; i < ans.size(); i++) printf(" %d", ans[i]); printf("\n"); } return 0; }