求出凸包和重心,然后一个个看凸包上的相邻点放在地面上能否放稳即可。
比赛中写的代码很搓。。。
/*
* Author: stormdpzh
* Created Time: 2012/8/17 15:10:30
* File Name: f.cpp
*/
#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <functional>
#define sz(v) ((int)(v).size())
#define rep(i, n) for(int i = 0; i < n; i++)
#define repf(i, a, b) for(int i = a; i <= b; i++)
#define repd(i, a, b) for(int i = a; i >= b; i--)
#define out(n) printf("%d\n", n)
#define mset(a, b) memset(a, b, sizeof(a))
#define wh(n) while(1 == scanf("%d", &n))
#define whz(n) while(1 == scanf("%d", &n) && n != 0)
#define lint long long
using namespace std;
const int INF = 1 << 30;
const int MaxN = 50005;
const double eps = 1e-12;
int sgn(double d)
{
if(d > eps) return 1;
if(d < -eps) return -1;
return 0;
}
struct Point {
double x, y;
Point() : x(0.0), y(0.0) {}
Point(double _x, double _y) : x(_x), y(_y) {}
void read() {
scanf("%lf%lf", &x, &y);
}
};
Point pnt[MaxN], res[MaxN];
int n;
Point core;
struct Node {
double x, dis;
Node() {}
Node(double _x, double _dis) : x(_x), dis(_dis) {}
bool operator < (const Node &t) const {
if(sgn(x - t.x) != 0) return sgn(x - t.x) < 0;
else return sgn(dis - t.dis) < 0;
}
};
set<Node> st;
set<Node>::iterator it;
int total;
bool mult(Point sp, Point ep, Point op)
{
return sgn((sp.x - op.x) * (ep.y - op.y) - (ep.x - op.x) * (sp.y - op.y)) >= 0;
}
bool operator < (const Point &l, const Point &r)
{
return sgn(l.y - r.y) < 0 || (sgn(l.y - r.y) == 0 && sgn(l.x - r.x) < 0);
}
Point operator - (const Point &l, const Point &r)
{
return Point(l.x - r.x, l.y - r.y);
}
double operator * (const Point &l, const Point &r)
{
return (l.x * r.x + l.y * r.y);
}
double operator ^ (const Point &l, const Point &r)
{
return (l.x * r.y - l.y * r.x);
}
int get_convex()
{
int i, len, k = 0, top = 1;
sort(pnt, pnt + n);
if (n == 0) return 0;
res[0] = pnt[0];
if (n == 1) return 1;
res[1] = pnt[1];
if (n == 2) return 2;
res[2] = pnt[2];
for (i = 2; i < n; i++) {
while (top && mult(pnt[i], res[top], res[top - 1])) top--;
res[++top] = pnt[i];
}
len = top;
res[++top] = pnt[n - 2];
for(int i = n - 3; i >= 0; i--) {
while(top != len && mult(pnt[i], res[top], res[top - 1])) top--;
res[++top] = pnt[i];
}
return top;
}
Point get_point()
{
Point p, s;
double tp, area = 0.0, tpx = 0.0, tpy = 0.0;
p.x = pnt[0].x; p.y = pnt[0].y;
for(int i = 1; i <= n; i++) {
s.x = pnt[(i == n) ? 0 : i].x;
s.y = pnt[(i == n) ? 0 : i].y;
tp = fabs((p.x * s.y - s.x * p.y));
area += tp / 2.0;
tpx += (p.x + s.x) * tp;
tpy += (p.y + s.y) * tp;
p.x = s.x;
p.y = s.y;
}
s.x = tpx / (6.0 * area);
s.y = tpy / (6.0 * area);
return s;
}
bool judge(int x, int y)
{
Point A = core - res[x];
Point B = core - res[y];
Point C = res[x] - res[y];
if(sgn(A * (Point(0.0, 0.0) - C) <= 0)) return false;
if(sgn(B * C) <= 0) return false;
return true;
}
double get_dis(int x, int y)
{
Point A = Point(0, 0) - res[x];
Point C = res[y] - res[x];
double area = fabs(A ^ C) / 2.0;
return (area / sqrt((res[x].x - res[y].x) * (res[x].x - res[y].x) + (res[x].y - res[y].y) * (res[x].y - res[y].y)));
}
bool is_low(int x, int y)
{
Point A = res[x], B = res[y];
if(sgn(A.x - B.x) == 0) return sgn(A.x) < 0;
if(sgn(A.y - B.y) == 0) return sgn(B.y) < 0;
double tmp = (-A.x) * (A.y - B.y) / (A.x - B.x) + A.y;
return sgn(tmp) < 0;
}
int gao()
{
int cnt = 0;
bool f = false;
bool d = 0.0;
st.clear();
for(int i = 0; i < total; i++) {
int j = (i + 1) % total;
double x;
double dis = get_dis(i, j);
if(is_low(i,j)) dis = -dis;
if(res[i].x - res[j].x == 0.0) {
if(!f || d != dis) {
if(judge(i, j)) {
cnt++;
f = true;
d = dis;
}
}
}
else {
x = (res[i].y - res[j].y) / (res[i].x - res[j].x);
if(st.find(Node(x, dis)) == st.end()) {
if(judge(i, j)) {
cnt++;
st.insert(Node(x, dis));
}
}
}
}
return cnt;
}
int main()
{
int t;
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = 0; i < n; i++) pnt[i].read();
core = get_point();
total = get_convex();
out(gao());
}
return 0;
}