算法题每日一练---第66天:平面切分

1,156 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、问题描述

平面上有 N 条直线,其中第 i 条直线是 y=Ai⋅x+Bi

请计算这些直线将平面分成了几个部分。

题目链接:平面切分

二、题目要求

样例

输入:
    3
    1 1
    2 2
    3 3
输出:
    6

考察

1.数学思想
2.建议用时20~35min

三、问题分析

假如问题改成:任意n条直线,最多可以将平面分成多少块区域?

1.png

如上图所示,直线对应的区域数量如下所示:

1             1
2             4
3             7
4             11
5             16
6             22
7             29
......
n             n*(n+1)/2+1

第n条直线区域数目=第n-1条直线区域数目+不同交点数目+1

任意n条直线,最多可以将平面分成 n*(n+1)/2+1块区域。

那么题目给定直线,面对不同的情况如何判断?

直线平行,区域=n+1
直线重合,区域=n+0
直线相交,区域=不同交点数目+1

四、编码实现

#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
using namespace std;
typedef pair<double,double>line;
typedef long long ll;
set<line>l;
int check(double a1,double b1)
{
	set<line>p;
	double a3,b3;
	for(set<line>::iterator it=l.begin();it!=l.end();it++)//取出已存在的优点
	{
		double a2=it->first;
		double b2=it->second;
		if(a2!=a1)//不平行
		{
			a3=(b1-b2)/(a2-a1);
			b3=a1*a3+b1;
			p.insert({a3,b3});//交点插入,判重
		}
	}
	return p.size();//返回大小
}
int main()
{
	ll i,n,ans=1;//初始化数据
	cin>>n;//输入直线数量
	double x,y;//直线坐标
	for(i=1;i<=n;i++)
	{
		cin>>x>>y;//输入
		if(!l.count({x,y}))//不是重复的直线
		{
			l.insert({x,y});//插入set判重
			ans+=check(x,y)+1;//求交点
		}               
	}
	cout<<ans;//返回结果
	return 0;
}

五、总结与提高

1.折线

f(n)=f(n-1)+4*(n-1)+1

f(n)=2n2n+12*n^2-n+1

2.三角形

f(n)=f(n-1)+6*(n-1)+1

f(n)=3n(n1)+2f(n)=3*n*(n-1)+2

3.圆形

f(n)=f(n-1)+2*(n-1)

f(n)=n2n+2f(n)=n^2-n+2

4.平面分割空间

f(n)=(n3+5n)/6+1(n^3+5*n)/6+1