目录
个人介绍:
各位CSDN的友友们,大家好,我是小熙,一个算法小透明,希望在CSDN的大舞台可以和大家一起取得进步(^_^)
个人现状:上个学期在学校的ACM小组学了一个学期的算法,但是世界很大,我的梦想很远,我希望在我年轻的时候可以走出国门,到世界的其他地方看一看,再加上我的算法功底可能真的不太足以支持我在ACM比赛上做出成绩。所以我选择逐渐淡出ACM小组,并把之前的知识整理成博客供大家分享。
学习算法的小方法:知道算法的基本原理——>知道代码实现——>总结出代码模板并熟练于心——>基本模板题——>变式思维题
几何问题的概况
有时候像一些公司的笔试题和一些杯赛喜欢出分割平面相关的几何题目,ICPC,CCPC的那我真的不会QWQ,但还是可以把其中的平面分割问题单独拿出来总结为结论题的。
直线分割平面的几何问题
结论
(1)n条直线最多把平面分为n*(n+1)/2+1个区域
(2)如果一个平面内只有直线,那么新加入一条直线,它所产生的平面数量为交点数加一,即使是与某条直线平行的话(交点为0)它也会产生一个平面的。
证明过程
(1):按理来讲其实就背记了上面的结论会用但是不会证明也没有关系,现在我们来给它证明一下下 。
证明说明:
如图:
(1)由于平面的大小是无穷的,不妨先用作一个圆当成辅助线把平面的范围框柱,反正所分割的平面的个数不会改变,图中原本有n条直线,新增一条直线,如图,必然会有新形成的线段,而这些新形成的线段正好可以分割平面,如果想要使新形成的平面区域数量越大,那么新形成的线段就要越多,而新加入的直线与原本直线的交点越多,新形成的线段就越多。
(2)接着(1)的推导,如果原本有n条直线,那么新加入的直线就可以与原直线有n个交点,(n+1)条线段,(n+1)个区域。
(3)公式的推导:f[n]表示n条直线形成的最大区域数量,f[n-1]表示n-1条直线形成的最大区域数量,f[n]=f[n-1]+n;然后就可以得出结论f[n]=n*(n+1)/2+1
例题
分析
在原本的平面中,如果新加入的那一条直线与原本的直线的交点数量为n,那么新产生的平面数量就是n+1。知道了这个性质,这就是一道结论题。
代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<double,double> pdd;
set<pdd>a;//先用set容器装直线,对直线进行去重操作
const int N=1e3+10;
pdd b[N];//以数组的方式存储去重之后的直线
int n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
double x,y;
cin>>x>>y;
a.insert({x,y});
}
int cnt=0;
for(set<pdd>::iterator it=a.begin();it!=a.end();it++,++cnt)//这是以迭代器的方式遍历set容器里面的每一个元素,背下来就可以了,反正搞明白也意义不大
{
double x=it->first;double y=it->second;
pdd temp;
temp.first=x;
temp.second=y;
b[cnt]=temp;
}//这一个部分的作用遍历set里面的每一个元素然后把他提取到数组b里面去
int ans=2;
//这一个步骤就是枚举直线了,第一层循环枚举2~i的每一个直线,第二层循环是第i条直线之前二代每一条直线。
for(int i=2;i<=cnt;i++)
{
set<double>t;//set<double>t用来装第i条加入的直线与之前加入的直线的交点
for(int j=1;j<i;j++)
{
double a1=b[i].first;
double a2=b[j].first;
double b1=b[i].second;
double b2=b[j].second;
if(a1!=a2)//不平行的话就求交点
{
double temp=(b2-b1)/(a1-a2);
t.insert(temp);
}
}
ans+=t.size()+1;//新增平面数量等于交点数量加一
}
cout<<ans;
return 0;
}
封闭图形的分割平面的几何问题
结论
n个闭合的曲线,所能够分割形成的最大区域数量为个
证明
不难知道如果平面中原有的闭合曲线的数量为n,新加一个闭合曲线,会产生2n条线段,新增了2n个区域。f[n]表示的是由n个闭合曲线时形成的最大区域数量。f[n]=f[n-1]+2*(n-1)不难推导出f[n]=n^2-n+2;
折线分割平面的几何问题
结论
结论:n条折线可以把平面分割为2n^2-n+1个区域。
证明
(1)还是一样,由于平面的大小是无穷的,不妨先用作一个圆当成辅助线把平面的范围框柱,反正所分割的平面的个数不会改变。新增一条折线会产生4n条线段,2条射线,(上图画圈的俩条就是射线)
(2)所以在原本有n个曲线的平面中,新增一个折线会产生(4n+2-1)个平面(要减去1是因为折线那边多算了一个平面,要减去)
例题
分析
来,套一手公式,先把20个圆放到平面里面去
(1)20个封闭曲线(圆)将平面最多分割为(20*20-20+2)即382个区域。
然后呢,把20条直线一条一条放平面里进去
(2)首先来看直线与圆相交产生的新的区域,这里就要分析下了。但是比较简单。
如图,不难推出一条直线与n条封闭曲线会产生2*n-1条线段(图中紫色的)和2条射线,所以线段会产生2*n-1个新增区域,而射线会新增一个区域,所以一共会新增2n个区域,综上,m条直接放入含有n个闭合曲线的平面最多含产生2nm个新增区域。结果就是2*20*20
(3)最后来看新加入的直线对直线的影响,由于这里直线不是第一个放入的,所以不可以套用n*(n+1)/2+1这个公式,其实吗,n*(n+1)/2+1来源于f[1]+2+3+.......+n(f[1]表示对的是只有一条直线的时候直线所分割的平面的数量)而这里由于加入直线之前就有曲线分割了平面,所以把f[1]去掉用2+3+......+n来算就可以了。就是(n+2)*(n-1)/2
代码
没有代码,直接手算,答案=(22*19)/2+(20*20-20+2)+(2*20*20)=1391
公式全家桶
直线分割平面:最多把平面分为n*(n+1)/2+1个区域
封闭曲线分割平面:最多把平面分为n^2-n+2个区域
折线分割平面:最多把平面分为2n^2-n+1个区域