链接:http://www.rqnoj.cn/problem/281
题意看不懂。。之后听yzy大佬解释才发现就是枚举环(出题人分不清线段和直线),使这个环包含所有点。那么暴搜dfs即可,枚举放点的顺序,用叉积判断放下这个点之后产生的线段是否会和之前放下的线段有交。
这里讲下叉积判线段交,主要就是跨立实验,ab线段与cd线段有交点(这里端点相交不算有交)时需满足((a->c)X(a->b))*((b->d)X(a->b))<0且((a->d)X(c->d))*((b->c)X(c->d)<0。
#pragma GCC optimize(3,"inline","Ofast")
#include<bits/stdc++.h>
using namespace std;
struct pt{
int x,y;
}node[15];
struct xd{
pt x,y;
void in(pt a,pt b)
{x=a,y=b;}
};
struct vec{
int x,y;
void in(pt a,pt b)
{
x=b.x-a.x;
y=b.y-a.y;
}
};
int cj(vec a,vec b)
{return a.x*b.y-a.y*b.x;}
int n,idx[15],ans=0;
bool vis[15];
bool line(xd x,xd y)
{
vec a,b,c,d,X,Y;
X.in(x.x,x.y);
Y.in(y.x,y.y);
a.in(x.x,y.x);
b.in(x.y,y.y);
c.in(x.x,y.y);
d.in(x.y,y.x);
if(cj(a,X)*cj(b,X)<0&&cj(c,Y)*cj(d,Y)<0)return 1;
return 0;
}
bool check(int pos,xd x)
{
xd y;
for(int i=2;i<=pos;i++)
{
y.in(node[idx[i-1]],node[idx[i]]);
if(line(x,y))return 0;
}
return 1;
}
void dfs(int pos)
{
xd tmp;
if(pos==n+1)
{
tmp.in(node[idx[n]],node[idx[1]]);
if(check(pos,tmp))
{
ans++;
}
return;
}
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
vis[i]=1,idx[pos]=i;
if(pos==1)
dfs(pos+1);
else
{
tmp.in(node[idx[pos-1]],node[idx[pos]]);
if(check(pos-1,tmp))
dfs(pos+1);
}
vis[i]=0;
}
}
}
int main()
{
n=0;
while(~scanf("%d",&node[++n].x))
{
scanf("%d",&node[n].y);
if(node[n].x==0&&node[n].y==0)break;
}
dfs(1);
cout<<ans/(2*n);
}