[bsoj1035] 点和线

该博客介绍了如何解决信息学竞赛中的一个计算几何问题,即在给定平面上的点中找出能构成不相交线段的多边形总数。通过爆搜和线段相交判断的方法,对四到十个点的情况进行分析并提供源代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


题目描述

平面上有一些点,你可以用直线将两点连接起来。那么有多少种方法可以把这些点连续地连起来,构成一个封闭的图形,使得任何两个线都不交叉,形成一个多边形。
显然,三个点只有一种方法。四个点最多只有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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值