大致题意:
8*8的整点格子,输入16个整点,求多少种点的集合可以组成正3,正4,5,6边形
思路:sb题啊...整点格子组成不了n !=4的所有正多边形,只要判是否能组成正方形就可以了
这里有个优美的无穷递降的证明:http://www.zhihu.com/question/25304120
而我是枚举所有点的集合判断是否能组成正多边形的蠢方法= =,先用凸包对点排个序,然后判各点距离相等和用余弦定理判个顶角相等.....
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstring> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <string> #include <vector> #include <cstdio> #include <ctime> #include <bitset> #include <algorithm> #define SZ(x) ((int)(x).size()) #define ALL(v) (v).begin(), (v).end() #define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i) #define reveach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i) #define REP(i,n) for ( int i=1; i<=int(n); i++ ) #define rep(i,n) for ( int i=0; i<int(n); i++ ) using namespace std; typedef long long ll; #define X first #define Y second typedef pair<int,int> pii; template <class T> inline bool RD(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void PT(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) pt(x / 10); putchar(x % 10 + '0'); } const int N = 25; pii poi[N]; int a[1<<20]; int top; inline int cal(int x){ int ans = 0; while(x) ans += x&1, x >>= 1; return ans; } int b[10]; int dis(pii &a,pii &b){ int A = a.X-b.X; int B = a.Y-b.Y; return A*A+B*B; } pii tmp[10]; bool cmp(pii a,pii b) { if(a.X==b.X)return a.Y<b.Y; return a.X<b.X; } int cross(pii a,pii b,pii c)//向量积 { return (a.X-c.X)*(b.Y-c.Y)-(b.X-c.X)*(a.Y-c.Y); } pii res[10]; int convex(int n)//求凸包上的点 { sort(tmp,tmp+n,cmp); int m=0,i,k; //求得下凸包,逆时针 //已知凸包点m个,如果新加入点为i,则向量(m-2,i)必定要在(m-2,m-1)的逆时针方向才符合凸包的性质 //若不成立,则m-1点不在凸包上。 for(i=0;i<n;i++) { while(m>1&&cross(res[m-1],tmp[i],res[m-2])<=0)m--; res[m++]=tmp[i]; } k=m; //求得上凸包 for(i=n-2;i>=0;i--) { while(m>k&&cross(res[m-1],tmp[i],res[m-2])<=0)m--; res[m++]=tmp[i]; } if(n>1)m--;//起始点重复。 return m; } int jiao(pii a,pii b,pii c){ return (b.X-a.X)*(c.X-a.X)+(b.Y-a.Y)*(c.Y-a.Y); } int t[10]; bool judge(int x){ int c = 0; for(int i = 0 ; (1<<i) <= x; i++){ if( x&(1<<i) ) tmp[c++] = poi[i+1]; } int n = convex(c); if( n != c) return false; REP(i,c) tmp[i] = res[i-1]; tmp[0] = tmp[c],tmp[c+1] = tmp[1]; REP(i,c) b[i] = dis(tmp[i],tmp[i+1]); for(int i = 2; i <= c;i++){ if( b[i] != b[i-1]) return false; } REP(i,c) t[i] = jiao(tmp[i],tmp[i-1],tmp[i+1]); for(int i = 2; i <= c ;i++) if( t[i] != t[i-1]) return false; return true; } int main(){ rep(i,1<<20) { int x = cal(i); if( x == 3 || x == 4 || x== 5 || x== 6) a[++top] = i; } int n; while(~scanf("%d",&n)){ REP(i,n) scanf("%d%d",&poi[i].X,&poi[i].Y); int ans = 0; REP(i,top){ if( a[i] > (1<<n) ) break; ans += judge(a[i]); } printf("%d\n",ans); } }