【蓝桥杯】平面切分(也是典型题型)(求n条直线划分的区域)

 解题思路

大多数人都是用找规律的方法解决。这种方法好归好,但并不是真正的意义上的解决。

几何题相对来说比较考验空间想象力、思维能力。越复杂的几何结构,其相对应的想象力、思维能力的要求也会越来越大。

对于本题,如果你是先让 N​​ 条直线同时添加在平面上,再统计答案,那么计算起来将会十分困难。

所以我们考虑将直线一条一条加入到平面上,并考虑每条直线加入后对答案的贡献(即加入一条直线后可以额外将平面划分成产生多少个部分)。

在开始之前,我们首先要知道,当一个直线经过一个平面(区域)后,它必然会将该平面划分成两个新的区域。

起初(未添加任何直线之前)整个平面只有一个区域,那么加入了第 1​ 条直线后,该直线会将平面划分成两个新的区域。

现在一共有两个区域。当我们再加入第 2 条直线后,它必然会先经过一个区域,并把该区域划分成两个新的区域。接着,如果它与第 1条直线相交,那么它将会从原来的区域进入到新的区域,并也会把区域划分成两个新的区域。

假设第 2 条直线与第 1 条直线相交,那么我们加入第 3 条直线后有以下两种情况:

  • 第 3 条直线与第 1、2 条直线交于两个不同的点。
  • 第 3 条直线与第 1、2​ 条直线交于相同的点。

对于第一种情况,第 3 条直线会先后进入另外的两个区域,并将这两个区域全都划分成两个新的区域。

对于第二种情况,第 3 条直线只会从一个区域到达另一个区域,并将该区域划分成两个新的区域,之后它将不会再进入别的区域。

从上我们可得,当添加一条直线后,它首先就会将开始所在的区域划分成两个新的区域(答案个数加一);接着随着它的扩张,如果它与别的直线相交于一个点,那么它就会从原来的区域到达另一个的区域,并把另一个的区域划分成两个新的区域(答案个数加一);接着若它再与别的直线相交于另外一个点,它就将再次进入另一个区域,并将该区域也划分成两个新的区域(答案个数加一)。那么一条直线对答案的贡献 =​ 1​ +​ 它与别的直线的交点个数 。 

最后模拟上述过程,并统计答案即可。(注意一条边可能多次出现,别忘了去重)

ACcode:

#include<iostream>
#include<set>
using namespace std;
set<pair<int,int>>line;
int n,ans=1;
int calc(int a,int b){//那么一条直线对答案的贡献
                    // ==1+它与别的直线的交点个数 。
	set<pair<double,double>>node;//记录(a,b)直线和其他直线交点个数 
	for(auto i:line){//遍历当已经存在的所有直线 
		int A=i.first,B=i.second;
		if(A==a)continue;//平行continue(平行造成的分割体现在return的+1)
		                 //画个简单的图就明白了 
		double x=1.0*(B-b)/(A-a);//交点的横坐标 
		double y=x*a+b;//交点的纵坐标 
		node.insert(make_pair(x,y));//入 
	}
	return node.size()+1;//那么一条直线对答案的贡献==1+它与别的直线的交点个数 。
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		int a,b;
		cin>>a>>b;
		if(line.find(make_pair(a,b))!=line.end())//判重
		//因为可能输入多个(a,b)相同的组 
		continue;
		ans+=calc(a,b);
		line.insert(make_pair(a,b));
	}
	cout<<ans<<"\n";
	return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值