【蓝桥杯真题】切分平面 --- 画图解析


往期蓝桥杯真题解析

【十二届蓝桥杯国赛真题】123 — 时间复杂度O(1)的纯数学解法

【蓝桥杯真题训练 day14】今日四道真题全解析

【蓝桥杯冲刺 day12】题目全解析

【蓝桥杯冲刺 day10】题目全解析 — 难题突破

【蓝桥杯冲刺 day8】题目全解析 —附上LeetCode 每日一题

【蓝桥杯冲刺 day7】 题目全解析 — 附上LeetCode周赛 银联-03. 理财产品

【蓝桥杯冲刺 day4】题目全解析 — 每日刷题解析


写在前面

大家好我是秋刀鱼,今天分享一下我的蓝桥杯省赛题目切分平面解题思路。


蓝桥杯省赛真题 平面切分

题目传送门🚀

问题描述

平面上有 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。

解题思路

这道题主要考察的是二维直线的相交性质,考试中可以通过画图来分析解决此类问题:

情况一:唯一的一条直线

image-20220329192034592

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

情况二:两直线平行

image-20220329192256387

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

情况三:相交的直线

image-20220329192515256

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

image-20220329193159674

新的直线与其他直线交点个数为: 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;
}

写在最后

代码、论述中有任何问题,欢迎大家指出,同时如果有任何疑问,也能够在评论区中留言,大家共同讨论共同进步!

如果觉得博主写的不错的话,可以点赞支持一下

img

  • 12
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋刀鱼与猫_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值