蓝桥杯[第十一届][B组]-平面切分
2022-04-04 18:25 幻霞 阅读(94) 评论(0) 编辑 收藏 举报这题用到欧拉定理
所以笔者去查了一下:https://baike.sogou.com/v163464.htm?fromTitle=%E6%AC%A7%E6%8B%89%E5%AE%9A%E7%90%86&ch=frombaikevr
欧拉是个著名的各种家,提出的理论有很多,非常厉害,这也导致笔者花了不少时间去找相关的结论。
结论如下:
欧拉发现,不论什么形状的凸多面体,其顶点数V、棱数E、面数F之间总有关系V+F-E=2,此式称为欧拉公式。V+F-E即欧拉示性数,已成为“拓扑学”的基础概念。
这个和平面唯一的不同就是这是三维的结论,而该题是二维的,那么怎么办?其实我们可以把当前题目构成的图形按着一个规律升维,比如
这个图形其实我们可以把线延长然后把它们连起来(这是直线,但为了方便处理,定义一个边界,把它们连起来)
结果就是这样:
棕色的线是增加在面内的线,和外围面的数量相同
接下来,我们可以把它想象成一个立体的,每一个线段作为一条棱,棕色线的作为底边的立体形状。这样
它就有28条棱,16个点,根据欧拉公式V+F-E=2我们可以得出(面数 = 棱数 - 点数 +2),也就是这里的28-16+2=14个面
去掉底面刚好就是13,是原图形的答案。
首先棱数 28 = 底边(原线数*2=10)+原线数(5)+点截线产生的新棱数(原点数*2+计算时重复的点的个数*1)
点数16 = 底边的点(原线数*2=10)+原点数(6)
注 :两个线相交他们互相切割形成两条新的线(也就是这里的棱),图中因为有三线共点,所以计算时重复的点只截了新加入的线,所以只加了一条棱。
综上所述,我们算得的平面状态面的数量为: 线数 + 点数+重复的点数+1。(地面点数和边数相同直接消掉了,去掉底面-1)
在这里 5 + 6 +1 +1 =13。另外这题可以用set集合去对输入输出和重复点去重。
代码如下:
#include <bits/stdc++.h> #include <stdlib.h> #include <set> #include <algorithm> using namespace std; set<pair<int ,int> > lines; set<pair<double ,double> > points; int n,m=0,num[1005]; int k,d; int main() { ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); cin>>n; for(int i=0; i<n; i++) { cin>>k>>d; lines.insert({k,d}); } for(set<pair<int,int> >::iterator l1=lines.begin(); l1!=lines.end(); l1++) { set<pair<double,double> > hasCut; for(set<pair<int,int> >::iterator l2=--lines.end(); l2!=l1; l2--) { if(l1->first-l2->first!=0) {//分母不为0 double x=(l1->second -l2->second)/(double)(l2->first- l1->first); double y= (l1->first)*x+l1->second; //对点集判断,已经出现才算重复,而且一条线不能被同一个点截两次 if(points.find({x,y})!=points.end() && hasCut.find({x,y}) == hasCut.end()) m++; points.insert({x,y}); hasCut.insert({x,y}); } } } cout<<lines.size()+points.size()+m+1<<endl; return 0; }
除了find函数其实还可以用count,因为集合相同元素只能有1个所以count只有0和1。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架