题目描述
平面上有一些点,你可以用直线将两点连接起来。那么有多少种方法可以把这些点连续地连起来,构成一个封闭的图形,使得任何两个线都不交叉,形成一个多边形。
显然,三个点只有一种方法。四个点最多只有3种方法。写一个程序计算方法总数。
输入格式
每一行是一个点的坐标,坐标值是整数,中间用一个空格隔开。最后一个坐标是原点。任意三点不在一条直线上。最多只有10个点。
输出格式
输出,方案总数。
样例数据
样例输入
100 -10
-200 0
45 7
0 0
样例输出
3
题目分析
爆搜+判断线段相交
源代码
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
struct Vector;
struct Point {
double x,y;
};
struct Vector {
double x,y;
};
Vector operator - (Point a,Point b) {
Vector c;
c.x=b.x-a.x;
c.y=b.y-a.y;
return c;
}
double Cross(Vector a,Vector b) { //叉积
return a.x*b.y-b.x*a.y;
}
bool Segment_Intersect(Point A,Point B,Point C,Point D) { //判断两线段是否相交
return (Cross((C-A),(D-A))*Cross((C-B),(D-B))<0)&&(Cross((A-C),(B-C))*Cross((A-D),(B-D))<0);
}
int n,ans[15],sum=0,vst[15];
Point a[15];
bool Check(int Depth,int x) {
for(int i=1; i<=Depth-2; i++)
if(Segment_Intersect(a[ans[i]],a[ans[i+1]],a[ans[Depth-1]],a[x]))return false;
return true;
}
void Dfs(int Depth) {
if(Depth==n+1) {
if(Check(Depth,1))sum++;
return;
}
for(int i=2; i<=n; i++)
if(!vst[i]&&Check(Depth,i)) {
vst[i]=1;
ans[Depth]=i;
Dfs(Depth+1);
vst[i]=0;
}
}
int main() {
int x,y;
while(scanf("%d%d",&x,&y)!=EOF) {
a[++n].x=x;
a[n].y=y;
}
vst[1]=1;
ans[1]=1;
Dfs(2);
printf("%d\n",sum/2);
return 0;
}