大致题意:
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);
}
}