往期蓝桥杯真题解析
【十二届蓝桥杯国赛真题】123 — 时间复杂度O(1)的纯数学解法
【蓝桥杯冲刺 day8】题目全解析 —附上LeetCode 每日一题
【蓝桥杯冲刺 day7】 题目全解析 — 附上LeetCode周赛 银联-03. 理财产品
写在前面
大家好我是秋刀鱼,今天分享一下我的蓝桥杯省赛题目切分平面解题思路。
蓝桥杯省赛真题 平面切分
问题描述
平面上有 N 条直线,其中第 i 条直线是 y=Ai⋅x+Bi。
请计算这些直线将平面分成了几个部分。
输入格式
第一行包含一个整数 N。
以下N行,每行包含两个整数 Ai,Bi。
输出格式
一个整数代表答案。
样例输入
3 1 1 2 2 3 3
Data
样例输出
6
Data
评测用例规模与约定
对于 50 的评测用例,1≤N≤4, −10≤Ai,Bi≤10。
对于所有评测用例,1≤N≤1000, −100000≤Ai,Bi≤100000。
解题思路
这道题主要考察的是二维直线的相交性质,考试中可以通过画图来分析解决此类问题:
情况一:唯一的一条直线

直线将原来的一个平面分割为 A , B A,B A,B 两个部分,交点的数量:0。分割部分数量+1 + 0
情况二:两直线平行

平行直线将 B B B 平面分割为 B , C B,C B,C 平面,交点的数量:0。分割部分数量+1+0
情况三:相交的直线

新的直线与其他直线的交点数量为: 2 2 2 ,分割部分数量 + 1 + 2

新的直线与其他直线交点个数为: 2 2 2 ,需要注意的是:右侧与两条直线相交,但交点均是同一个点,不能重复计算。
该情况下得到:分割的部分数量 + 1 + 2
总结
不难发现规律:每一条直线增加的分割部分数量为: N + 1 N+1 N+1 ,其中 N N N 是该直线与其他直线相交的点数量
于是我们可以用 p a i r < i n t , i n t > pair<int,int> pair<int,int> 存储直线的斜率 k k k 与偏移量 b b b ,新增一条直线时,将该直线与之前加入的所有直线进行计算判断是否相交,即 k k k 是否相同。如果相交则计算出相交点的坐标 ( x , y ) (x,y) (x,y) 并存入 s e t set set 中,最终得相交点的个数更新答案。
AC代码
#include <iostream>
#include <string.h>
#include <math.h>
#include <vector>
#include <set>
#include <stack>
#define ll long long
#define pii pair<int,int>
#define pdd pair<double,double>
using namespace std;
int main()
{
int n;
cin >> n;
// 存储加入直线
set<pii>points;
// 存储结果值
int ans = 1;
for (int i = 0; i < n; ++i) {
int a, b;
cin >> a >> b;
// 直线存在,不需要计算
if (points.count({ a,b })) {
continue;
}
// 存放所有交点信息
set<pdd>used;
int count = 0;
ans += 1;
// 遍历
for(set<pii>::iterator it = points.begin(); it != points.end();++it){
pii cur = *it;
// 斜率相同,没有交点
if (cur.first == a) {
continue;
}
// 获得交点坐标
double x = ((double)cur.second - b) / ((double)a - cur.first);
double y = a * x + b;
if (!used.count({ x,y })) {
++count;
used.insert({ x,y });
}
}
points.insert({ a,b });
ans += used.size();
}
cout << ans;
return 0;
}
写在最后
代码、论述中有任何问题,欢迎大家指出,同时如果有任何疑问,也能够在评论区中留言,大家共同讨论共同进步!
如果觉得博主写的不错的话,可以点赞支持一下!