题意:有n个点,要求每个点都要是凸多边形的一个顶点,且边不交叉,每个点只有两条边和他相连,要求顺序输出凸多边形的形状也就是各个顶点的编号,不存在就输出Impossible。
题解:首先容易想到Impossible的情况只有n点共线时会出现,用凸包函数求出凸包后,如果少于3个点就是Impossible。特判后,再用一次凸包,这次求凸包要包括共线点,下凸包的点是答案数组的前半部分。然后把所有点(不是只有凸包上的点)排序从右到左,从上到下排序,最右边的点一定在凸包上,从最右边的点开始,按顺序保存未被访问过的点(也就是除下凸包外所有点)到答案数组里,这些点是答案数组的后半部分。
#include
#include
#include
#include
#include
using namespace std;
const double eps = 1e-9;
const double PI = acos(-1);
double Sqr(double x) { return x * x; }
int dcmp(double x) { if (fabs(x) < eps) return 0; return x > 0 ? 1 : -1; }
struct Point {
double x, y;
int id;
Point(double a = 0, double b = 0): x(a), y(b) {}
};
typedef Point Vector;
typedef vector Polygon;
Vector operator + (const Vector& a, const Vector& b) { return Vector(a.x + b.x, a.y + b.y); }
Vector operator - (const Vector& a, const Vector& b) { return Vector(a.x - b.x, a.y - b.y); }
Vector operator * (const Vector& a, double b) { return Vector(a.x * b, a.y * b); }
Vector operator / (const Vector& a, double b) { return Vector(a.x / b, a.y / b); }
bool operator == (const Vector& a, const Vector& b) { return !dcmp(a.x - b.x) && !dcmp(a.y - b.y); }
bool operator < (const Vector& a, const Vector& b) { return a.x < b.x || (a.x == b.x && a.y < b.y); }
double Dot(const Vector& a, const Vector& b) { return a.x * b.x + a.y * b.y; }
double Length(const Vector& a) { return sqrt(Dot(a, a)); }
double Cross(const Vector& a, const Vector& b) { return a.x * b.y - a.y * b.x; }
double Angle(const Vector& a, const Vector& b) { return acos(Dot(a, b) / Length(a) / Length(b)); }
double angle(Vector v) { return atan2(v.y, v.y); }
int ConvexHull1(Point* P, int cnt, Point* res) {
sort(P, P + cnt);
cnt = unique(P, P + cnt) - P;
int m = 0;
for (int i = 0; i < cnt; i++) {
while (m > 1 && Cross(res[m - 1] - res[m - 2], P[i] - res[m - 2]) <= 0)
m--;
res[m++] = P[i];
}
int k = m;
for (int i = cnt - 2; i >= 0; i--) {
while (m > k && Cross(res[m - 1] - res[m - 2], P[i] - res[m - 2]) <= 0)
m--;
res[m++] = P[i];
}
if (cnt > 1) m--;
return m;
}
int ConvexHull(Point* P, int cnt, Point* res, int* num) {
sort(P, P + cnt);
cnt = unique(P, P + cnt) - P;
int m = 0;
for (int i = 0; i < cnt; i++) {
while (m > 1 && Cross(res[m - 1] - res[m - 2], P[i] - res[m - 2]) < 0)
m--;
num[m] = P[i].id;
res[m++] = P[i];
}
int k = m;
for (int i = cnt - 2; i >= 0; i--) {
while (m > k && Cross(res[m - 1] - res[m - 2], P[i] - res[m - 2]) < 0)
m--;
num[m] = P[i].id;
res[m++] = P[i];
}
if (cnt > 1) m--;
return m;
}
int cmp(Point a, Point b) {
if (a.x != b.x)
return a.x > b.x;
return a.y > b.y;
}
const int N = 2 * 1e3 + 5;
int n, num[N], vis[N], ans[N];
Point P[N], res[N];
int main() {
int t, cas = 1;
scanf("%d", &t);
while (t--) {
int nnn = 0;
memset(vis, 0, sizeof(vis));
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%lf%lf", &P[i].x, &P[i].y);
P[i].id = i;
}
int cnt1 = ConvexHull1(P, n, res);
if (cnt1 <= 2) {
printf("Case %d:\nImpossible\n", cas++);
continue;
}
int cnt = ConvexHull(P, n, res, num);
for (int i = 0; i < cnt; i++)
vis[num[i]] = 1;
sort(P, P + n, cmp);
int id1 = P[0].id;
printf("Case %d:\n", cas++);
int i;
for (i = 0; i < cnt; i++) {
if (num[i] == id1)
break;
ans[nnn++] = num[i];
}
for (; i < cnt; i++)
vis[num[i]] = 0;
for (int j = 0; j < n; j++)
if (!vis[P[j].id])
ans[nnn++] = P[j].id;
printf("%d", ans[0]);
for (int j = 1; j < nnn; j++)
printf(" %d", ans[j]);
printf("\n");
}
return 0;
}