平面切分
平面上有 N N N 条直线,其中第 i i i 条直线是 y = A i × x + B i y = A_i \times x + B_i y=Ai×x+Bi
请计算这些直线将平面分成了几个部分。
输入描述
第一行包含一个整数
N
N
N。
以下 N N N 行,每行包含两个整数 A i , B i A_i, B_i Ai,Bi
其中, 1 ≤ N ≤ 1000 , − 1 0 5 ≤ A i , B i ≤ 1 0 5 1 \leq N \leq 1000, −10^5 \leq A_i,B_i \leq 10^5 1≤N≤1000,−105≤Ai,Bi≤105。
输出描述
一个整数代表答案。
输入输出样例
输入
3
1 1
2 2
3 3
输出
6
思路
- 暴力法,因为数据范围就只有 1 0 3 10^3 103
- 理解直线切分平面的本质:交点数。即每增加 k k k 个交点,则增加 k + 1 k+1 k+1 个平面
- 暴力法枚举直线,求交点个数即可
代码如下
#include <math.h>
#include <iostream>
#include <set>
using namespace std;
set<pair<int, int>> line; //输入的直线
set<pair<pair<int, int>, pair<int, int>>> point; //交点集合
int n; //直线条数
int ans; //答案,最终的平面数
//求最大公约数
int gcd(int m, int n) {
if (n == 0) return m;
return gcd(n, m % n);
}
//化为最简分数
pair<int, int> cal(pair<int, int> a) {
int x = abs(a.first);
int y = abs(a.second);
int gcd_num = gcd(x, y);
if (a.first * a.second < 0) {
return make_pair(-(x / gcd_num), y / gcd_num);
} else {
return make_pair(x / gcd_num, y / gcd_num);
}
}
//解决问题
void solve() {
pair<int, int> tmp;
pair<pair<int, int>, pair<int, int>> pot;
scanf("%d", &n);
scanf("%d%d", &tmp.first, &tmp.second);
line.insert(tmp);
ans = 2;//初始时有1条直线,2个平面
for (int i = 1; i < n; i++) {
scanf("%d%d", &tmp.first, &tmp.second);//输入一条直线的k,b,相当于输入一条直线
//判断是否已经有这条直线
if (line.find(tmp) == line.end()) {
//求这条直线与其余直线的交点
//方法为:求出与其他直线的交点,用最简分数形式表示,放入集合中,最后求这个交点集合的大小,即为交点个数
for (auto e : line) {
if (tmp.first != e.first) {
pot.first.first = tmp.second - e.second;
pot.first.second = e.first - tmp.first;
pot.second.first =
e.first * tmp.second - tmp.first * e.second;
pot.second.second = pot.first.second;
point.insert(make_pair(cal(pot.first), cal(pot.second)));
}
}
ans += (int)point.size() + 1;
point.clear();//每加入一条直线,交点集合就要清空一次
line.insert(tmp);//把这条直线加入进去
}
}
printf("%d\n", ans);//输出答案
}
int main(void) {
solve();
return 0;
}