这题严格来说不是凸包的题,只是用到了凸包的卷包裹的思想。。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef struct point {
double x;
double y;
int num;
}point;
typedef struct v {
point start;
point end;
}v;
double crossProduct(v* v1, v* v2)
{
v vt1, vt2;
double result = 0;
vt1.start.x = 0;
vt1.start.y = 0;
vt1.end.x = v1->end.x - v1->start.x;
vt1.end.y = v1->end.y - v1->start.y;
vt2.start.x = 0;
vt2.start.y = 0;
vt2.end.x = v2->end.x - v2->start.x;
vt2.end.y = v2->end.y - v2->start.y;
result = vt1.end.x * vt2.end.y - vt1.end.y * vt2.end.x;
return result;
}
const int maxn = 55;
const double eps = 1e-8;
point plant[maxn];
int m, n, cnt;
bool vis[maxn];
int path[maxn];
int main()
{
for(scanf("%d", &m); m--;) {
int st = 0;
cnt = 1;
scanf("%d", &n);
memset(vis, false, sizeof(vis));
for(int i = 0; i < n; i++) {
scanf("%d%lf%lf", &plant[i].num, &plant[i].x, &plant[i].y);
plant[i].num--;
if(plant[i].y < plant[st].y) st = i;
}
point sp;
sp.x = 0;
sp.y = plant[st].y;
v v0, v1, v2;
v0.start = sp;
v0.end = plant[st];
vis[st] = true;
path[0] = st;
bool found;
do {
found = false;
for(int i = 0; i < n; i++) {
if(vis[i]) continue;
v1.start = v0.end;
v1.end = plant[i];
if(crossProduct(&v0, &v1) >= 0) {
if(!found) {
found = true;
v2 = v1;
}
else {
if(crossProduct(&v1, &v2) > 0 || (fabs(crossProduct(&v1, &v2)) < eps && v1.end.x < v2.end.x))
v2 = v1;
}
}
}
if(found) {
v0 = v2;
vis[v2.end.num] = true;
path[cnt++] = v2.end.num;
}
}while(found);
printf("%d", cnt);
for(int i = 0; i < cnt; i++)
printf(" %d", path[i] + 1);
printf("\n");
}
return 0;
}
/*
100
3
1 1 1
2 2 1
3 3 2
*/