当前位置: 首页 > news >正文

P8720 [蓝桥杯 2020 省 B2] 平面切分

题目描述

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

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

输入格式

第一行包含一个整数 N。

以下 N 行, 每行包含两个整数 Ai​,Bi​。

输出格式

一个整数代表答案。

输入输出样例

输入 #1复制

3
1 1
2 2
3 3

输出 #1复制

6

说明/提示

对于 50% 的评测用例, 1≤N≤4,−10≤Ai​,Bi​≤10。

对于所有评测用例, 1≤N≤1000,−10^5≤Ai​,Bi​≤10^5。

蓝桥杯 2020 第二轮省赛 B 组 I 题

解题思路:

这题我们首先需要定义一个包含两个元素的对象typedef pair<int int >PII;和typedef pair<double double>PDD;,这两个PII一个用来存储每次输入斜线的斜率k和截距b,PDD则是用来存储新添加的线的焦点坐标线x,y,      其次就是定义set<PII>lines,进行出入将输入的的k,b通过lines.insert(k,b)进行存储,“这里利用set容器的去重判断是否有不重复的线加入,不重复的线必定相交”,这就进入到Get_point 函数中进行

// 函数:计算当前直线与已存在的直线交点的个数
int get_point(int k, int b) {
    set<PDD> point;  // 用于存储当前直线与其他直线的交点 (x, y)
    
    // 遍历所有已存在的直线
    for (it = lines.begin(); it != lines.end(); it++) {
        int K = it->first;  // 已存在直线的斜率
        int B = it->second;  // 已存在直线的截距

        // 如果两条直线的斜率不同,则计算交点
        if (K != k) {
            double x = 1.0 * (B - b) / (k - K);  // 计算交点的 x 坐标
            double y = 1.0 * k * x + b;  // 计算交点的 y 坐标
            point.insert({x, y});  // 将交点加入集合,避免重复
        }
    }

    // 返回交点的数量
    return point.size();
}

如果有新的交点最终的平面被划分为:新的交点个数+1;依次累加

 C++ STL(标准模板库)中的 set 容器与迭代器 的使用。以下是对其中涉及到的知识点:

1. typedef 的使用

typedef 是 C++ 中的一个关键字,用于给现有的数据类型定义一个新的名字(别名)。这在代码中非常常见,尤其是在类型较长或者复杂时,使用 typedef 可以提高代码的可读性和简洁性。

示例:typedef pair<double, double> PDD;
  • pair<double, double>:是 C++ STL 中的一个模板类,它用来存储一对值,通常用于表示关联数据,如 (x, y) 坐标或 (key, value) 键值对。

    • double 类型表示浮点数,pair<double, double> 存储的是两个浮点数。

    • pair 是一个模板类,它可以接受任意类型作为参数,表示一对值。pair<double, double> 表示存储两个 double 类型的值。

  • typedef pair<double, double> PDD;:给 pair<double, double> 这个类型起了一个别名,叫做 PDD。以后我们可以直接使用 PDD 来代替 pair<double, double>,使代码更加简洁和易于理解。

    例子:

    PDD point = {3.5, 4.2};  // 创建一个 PDD 类型的变量,表示点 (3.5, 4.2)
    cout << point.first << ", " << point.second << endl;  // 输出 3.5, 4.2
    
示例:typedef pair<int, int> PII;
  • pair<int, int>:同样是 C++ STL 中的一个 pair 类型,表示一个包含两个 int 类型元素的对象。这里的 int 类型通常用于表示整数,比如直线的斜率 k 和截距 b

  • typedef pair<int, int> PII;:给 pair<int, int> 这个类型起了一个别名,叫做 PII。以后我们可以直接使用 PII 来代替 pair<int, int>,简化代码。

    例子:

    PII line = {2, 3};  // 创建一个 PII 类型的变量,表示直线 y = 2x + 3
    cout << line.first << ", " << line.second << endl;  // 输出 2, 3
    

2. set 容器

set 是 C++ STL(标准模板库)中的一个关联容器,它存储唯一的元素,并且这些元素会按照某种排序规则(默认是升序)自动排序。set 容器不允许有重复元素。

  • 基本特性

    • 自动排序set 内部的元素会根据 operator< (默认)或者自定义的比较规则进行自动排序。

    • 元素唯一性set 中的元素不能重复,若尝试插入重复的元素,插入操作将会失败。

  • 用法:在这段代码中,set<PII> 用来存储一组直线的斜率和截距,PIIpair<int, int> 类型,即每个元素是一个表示直线的 (k, b) 对。

    set<PII> lines;  // 声明一个 set 容器,用于存储 (k, b) 形式的直线
    
    • 通过 insert 方法将新的直线加入 set 中:

      lines.insert({2, 3});  // 插入直线 y = 2x + 3
      lines.insert({1, 1});  // 插入直线 y = x + 1
      
    • 插入时,set 会自动对直线的 (k, b) 进行排序,按照斜率 k 和截距 b 的升序排列。

    • 由于 set 中的元素是唯一的,如果你尝试插入一个重复的 (k, b),插入操作将会失败(即元素不会被加入)。

3. 迭代器:set<PII>::iterator it;

iterator 是一种遍历 C++ STL 容器的对象,用于访问容器中的元素。

  • set<PII>::iterator it 声明了一个迭代器 it,用于遍历 set<PII> 容器中的元素。这里,it 会指向 set 中每一个存储的 PII 类型的元素(即 pair<int, int>)。

  • 迭代器的常见用法是通过 it 来访问容器中的元素,通常使用 begin() 获取指向容器第一个元素的迭代器,使用 end() 获取指向容器最后一个元素之后的位置的迭代器。

    例如:

    for (it = lines.begin(); it != lines.end(); ++it) {
        cout << it->first << ", " << it->second << endl;  // 输出每条直线的 k 和 b
    }
    
    • it->first 表示当前直线的斜率 k

    • it->second 表示当前直线的截距 b

总结

  • typedef pair<double, double> PDD;typedef pair<int, int> PII; 通过 typedefpair 类型起了别名,使得代码更简洁,方便表示坐标和直线的斜率与截距。

  • set<PII> 是一个 set 容器,存储 PII 类型的元素,每个元素表示一条直线的斜率和截距。set 容器保证元素的唯一性,并且会自动按升序排列。

  • set<PII>::iterator it 是用于遍历 set<PII> 容器的迭代器,能够按顺序访问每条直线的斜率和截距。

这些概念和容器在实际编程中非常常见,能够帮助我们高效地处理和存储一组数据,尤其是需要自动排序且不允许重复的场景。

#include<bits/stdc++.h>
using namespace std;

// 宏定义和类型别名
#define rep(x,y,z),for(int x=y;x<=z;x++)  // 用于简化循环结构
typedef pair<double, double> PDD;       // 用于表示交点的坐标对 (x, y)
typedef pair<int, int> PII;             // 用于表示直线的斜率 (k) 和截距 (b)
set<PII> lines;  // 用于存储平面上的所有直线,每个元素为一条直线的 (k, b)
set<PII>::iterator it;  // 用于遍历 'lines' 集合
int ans = 1;  // 初始区域数,平面没有直线时为 1
int n, k, b;  // n 表示直线数量,k 和 b 分别表示当前直线的斜率和截距

// 函数:计算当前直线与已存在的直线交点的个数
int get_point(int k, int b) {
    set<PDD> point;  // 用于存储当前直线与其他直线的交点 (x, y)
    
    // 遍历所有已存在的直线
    for (it = lines.begin(); it != lines.end(); it++) {
        int K = it->first;  // 已存在直线的斜率
        int B = it->second;  // 已存在直线的截距

        // 如果两条直线的斜率不同,则计算交点
        if (K != k) {
            double x = 1.0 * (B - b) / (k - K);  // 计算交点的 x 坐标
            double y = 1.0 * k * x + b;  // 计算交点的 y 坐标
            point.insert({x, y});  // 将交点加入集合,避免重复
        }
    }

    // 返回交点的数量
    return point.size();
}

int main() {
    cin >> n;  // 输入直线的数量

    // 循环处理每一条直线
    while (n--) {
        cin >> k >> b;  // 输入当前直线的斜率 k 和截距 b

        int cnt = lines.size();  // 获取当前已存在的直线数
        lines.insert({k, b});  // 将当前直线加入到集合中

        // 如果直线集合的大小发生变化,说明当前直线是新加入的
        if (cnt != lines.size()) {
            // 更新区域数:新增的直线会通过交点增加区域数
            ans += get_point(k, b) + 1;  // 增加的区域数 = 交点数 + 1
        }
    }

    // 输出最终的区域数
    cout << ans;
    return 0;
}

相关文章:

  • 深度学习环境安装
  • [蓝桥杯 2017 省 B] k 倍区间
  • Unity检索一个物体下所有的子物体,只打印激活的物体
  • 【8】搭建k8s集群系列(二进制部署)之安装work-node节点组件(kubelet)
  • 实操(不可重入函数、volatile、SIGCHLD、线程)Linux
  • 从奖励到最优决策:动作价值函数与价值学习
  • UNet 改进(2):深入解析带有坐标注意力机制(CA)的UNet网络
  • go垃圾回收机制
  • Java全栈面试宝典:锁机制与Spring生命周期深度解析
  • edge webview2 runtime跟Edge浏览器软件安装包双击无反应解决方法
  • 探秘JVM内部
  • 流浪动物救助|基于Springboot+vue的流浪动物救助平台设计与实现(源码+数据库+文档)
  • 如何单独指定 Android SDK tools 的 monitor.bat 使用特定 JDK 版本
  • 论伺服电机在轨道式巡检机器人中的优势及应用实践​
  • 《QT从基础到进阶·七十四》Qt+C++开发一个python编译器,能够编写,运行python程序改进版
  • AIDD-深度学习 MetDeeCINE 破译代谢调控机制
  • 达芬奇预设:复古16mm胶片质感老式电影放映机转场过渡+音效
  • 《C++后端开发最全面试题-从入门到Offer》目录
  • WEB安全--XSS--XSS基础
  • ②(PROFINET 转 Modbus TCP)EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关
  • 兰州网站设计/宁波优化关键词首页排名
  • 物流网站制作/semir是什么品牌
  • 平台建站建设/综合性b2b电子商务平台网站
  • qq客服代码放在网站哪里/抖音推广
  • .我爱你 网站/全网推广外包公司
  • 电子商务网站建设与维护pdf/谷歌搜索引擎香港入口