题目:http://acm.hdu.edu.cn/showproblem.php?pid=3685
题意:给一个简单多边形,求有几种平放在桌面上的方法。
思路:先求重心,再求凸包,枚举凸包上的每条边,判断重心在边上的投影是否在边上,注意投影恰好在端点不算答案,累加即可
//
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<vector>
#include<map>
#define FOR(i,s,t) for(int i=(s);i<=(t);i++)
#define CFOR(i) for(;i>0;i--)
#define DFOR(i,s,t) for(int i=(s);i>=(t);i--)
#define PFOR(i,s,t,p) for(int i=(s);i<=(t);i+=p)
#define SD(i) scanf("%d",&i)
#define SLLD(i) scanf("%lld",&i)
#define MEM(a,t) memset(a,t,sizeof(a))
#define PIA system("pause")
#define MAXINT 0xfffffff
#define MARK cout<<"MARK"<<endl;
#define BUG cout<<"error!"<<endl;
#define LL long long
using namespace std;
ifstream fin ("in.txt");
ofstream fout ("out.txt");
const double eps = 1e-8;
double sqr(double x){
return x*x;
}
int cmp(double x){
if( fabs(x)<eps ) return 0;
if(x>0) return 1;
return -1;
}
struct point{
double x,y;
point(){}
point(double a,double b) :x(a),y(b){}
friend point operator + (const point &a,const point &b){
return point(a.x+b.x,a.y+b.y);
}
friend point operator - (const point &a,const point &b){
return point(a.x-b.x,a.y-b.y);
}
friend bool operator == (const point &a,const point &b){
return cmp(a.x-b.x)==0 && cmp(a.y-b.y)==0;
}
friend point operator * (const point &a,const double &b){
return point(a.x*b,a.y*b);
}
friend point operator * (const double &a,const point &b){
return point(a*b.x,a*b.y);
}
friend point operator / (const point &a,const double &b){
return point(a.x/b,a.y/b);
}
double norm(){
return sqrt(sqr(x)+sqr(y));
}
void output(){
printf("(%.4f,%.4f)",x,y);
}
};
double det(const point &a,const point &b){
return a.x*b.y - a.y*b.x;
}
double dot(const point &a,const point &b){
return a.x*b.x + a.y*b.y;
}
struct line{
point p,v;
line(){}
line(point pp,point vv){p=pp;v=vv;}
point normal(){
return point(-v.y,v.x);
}
};
inline point intersect(const line &la, const line &lb) {
double t = det(lb.v, la.p - lb.p) / det(la.v, lb.v);
return la.p + la.v * t;
}
point point_line_foot(point p,line s){
line ln = line(p,s.normal());
return intersect(ln,s);
}
struct polygon_convex{
vector<point>P;
polygon_convex(int Size=0){
P.resize(Size);
}
};
bool comp_less(const point &a,const point &b){
return cmp(a.x-b.x)<0 || cmp(a.x-b.x)==0 && cmp(a.y-b.y)<0;
}
polygon_convex convex_hull(vector<point>a){
polygon_convex res(2*a.size()+5);
sort(a.begin(),a.end(),comp_less);
a.erase(unique(a.begin(),a.end()),a.end());
int m=0;
FOR(i,0,a.size()-1){
while(m>1&&cmp(det(res.P[m-1]-res.P[m-2],a[i]-res.P[m-2]))<=0) m--;
res.P[m++]=a[i];
}
int k=m;
DFOR(i,int(a.size())-2,0){
while(m>k&&cmp(det(res.P[m-1]-res.P[m-2],a[i]-res.P[m-2]))<=0) m--;
res.P[m++]=a[i];
}
res.P.resize(m);
if(a.size()>1) res.P.resize(m-1);
return res;
}
struct segment{
point a,b;
segment(){}
segment(point aa,point bb){a=aa;b=bb;}
};
int point_on_seg(point p,segment s){
return cmp(dot(point(s.a-p),point(s.b-p)));
}
/****************************************************************************************************/
vector<point>a;
polygon_convex pca;
int n;
void init(){
scanf("%d",&n);
double vx,vy;
a.clear();
FOR(i,1,n){
scanf("%lf %lf",&vx,&vy);
a.push_back(point(vx,vy));
}
}
void solve(){
//ÇóÓÐÏòÃæ»ý
double asum=0;
asum += det(a[0],a[a.size()-1]);
FOR(i,0,a.size()-2){
asum += det(a[i+1],a[i]);
}
asum /= 2;
//ÇóÖØÐÄ
point g=point(0,0);
FOR(i,0,a.size()-2){
g = g+(a[i]+a[i+1])*det(a[i+1],a[i]);
}
g = g+(a[a.size()-1]+a[0])*det(a[0],a[a.size()-1]);
g = g/asum/6;
//͹°ü
pca = convex_hull(a);
int size = pca.P.size();
int ans=0;
FOR(i,0,size-1){
line s;
if( i==size-1 ) s = line(pca.P[i],pca.P[0]-pca.P[i]);
else s = line(pca.P[i],pca.P[i+1]-pca.P[i]);
point fot = point_line_foot(g,s);
if( point_on_seg( fot,segment(s.p,s.p+s.v) )<0 ) ans++;
}
cout<<ans<<endl;
}
int main(){
// freopen("in.txt","r",stdin);
int T;scanf("%d",&T);
CFOR(T){
init();
solve();
}
return 0;
}