蓝桥杯 平面切分
一、题目
二、题解
问题1: n条直线可以将一个平面划分成多少个部分平面?注意:这些直线有可能平行,也可能几条直线相较于一个交点!
解决步骤:
- 不要想着一次性就将所有直线放到这些平面上,应该一条一条的把直线放到平面上。
- 每次放入一条直线,看看
这条直线
会与平面上已有的直线
产生多少个不同的交点。假如会产生a个交点,那么可以知道,放入了这条直线后,部分平面的个数会增加a+1
。- 从第1条直线开始放置到平面上,直至放置第n条结束。将每次放入一条直线后部分平面个数增加的个数累加起来就是最终的答案。
对上面的下划线处的内容的做如下解释:
第一幅图中是已经放置了5条直线,如果再放入第6条直线(绿色),可知这条
绿色直线
与原来的直线
的交点的个数为3个,那么,部分平面的个数就会增加
3+1个[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q3ui43nP-1622984702331)(typoraPicture/c++常用函数快速入门/image-20210606204304229.png)]
问题2: n条直线最多
可以将部分平面分为多少个部分?
从问题1的讨论知道,如果每次放入一条直线都与原来的直线相交(即没有平行线),且产生的交点与原来直线的交点没有重合,那么此时放入了该直线之后,部分平面的个数增加就会最多!
放第1条 放第2条 放第3条 放第4条 … 放第n条 新直线与原直线的交点个数 0 1 2 3 … n-1 部分平面增加的个数 0+1= 1
1+1= 2
2+1= 3
3+1= 4
… n-1+1= n
放入第一条直线之前,只有1个平面。那么,放入第1条、第2条、第3条…、第n条之后,总的平面个数为:1+
1
+2
+3
+4
+…+n
= 1+(n+1)*n/2所以,n条直线最多可以将部分平面分为
1+(n+1)*n/2
个部分
程序
程序暂时没有进行优化,能通过全部测试用例。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
int main()
{
int N = 0;
int plans = 0;
cin >> N;
set<pair<double, double> > setab; //使用set来存储a b值对,会自动剔除重复的a b值
for(int i=0; i<N; i++){
pair<double, double> temp;
cin >> temp.first >> temp.second;
setab.insert(temp);
}
set<pair<double, double> >::iterator iter1 = setab.begin();
set<pair<double, double> > _setab; //不停的向其中添加直线
for(; iter1!=setab.end(); iter1++){
pair<double, double> temp = *iter1;
if(_setab.size() <= 0){//当前_setab集合为空则直接插入到该集合中
_setab.insert(temp);
plans = 2;
continue;
}
//将该直线与所有已有直线对比
double a1=temp.first, b1=temp.second;
double x, y;
double a2, b2;
set<pair<double, double> > setcp; //存储直线交点
set<pair<double, double> >::iterator iter2 =_setab.begin();
for(; iter2!=_setab.end(); iter2++){
a2=iter2->first; b2=iter2->second;
if(a1-a2 == 0){//平行则说明没有交点
_setab.insert(temp);
continue;
}
x=(b2-b1)/(a1-a2); y=(a1*b2-a2*b1)/(a1-a2);
setcp.insert(pair<double, double>(x, y));
}
//则增加的平面数量 = 与已有直线交点的个数 + 1
plans += (setcp.size()+1);
_setab.insert(temp);
}
cout << plans << endl;
return 0;
}