蓝桥杯-数三角(ac代码时间复杂度分析)

news2024/10/6 0:35:45

问题描述

小明在二维坐标系中放置了 ( n ) 个点,他想在其中选出一个包含三个点的子集,这三个点能组成三角形。然而这样的方案太多了,他决定只选择那些可以组成等腰三角形的方案。请帮他计算出一共有多少种选法可以组成等腰三角形?

输入格式

输入共 ( n+1 ) 行。

第一行为一个正整数 ( n )。

后面 ( n ) 行,每行两个整数 ( x_i ) 和 ( y_i ) 表示第 ( i ) 个点的坐标。

输出格式

输出共 1 行,一个整数。

样例输入

5
1 1
4 1
1 0
2 1
1 2

样例输出

4

评测用例规模与约定

  • 对于 20% 的数据,保证 ( n <= 200)。
  • 对于 100% 的数据,保证 ( n <= 2000),( 0 <= xi, yi <= 1e9)。

题解:

正常的暴力代码👇 时间复杂度O(n^3) 会超时, 只过了不到一半数据

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

const signed N = 1e4;

int a[N], b[N];

signed main()
{
	signed n; cin >> n;
	for (signed i = 0; i < n; i ++) cin >> a[i] >> b[i];
	
	int cnt = 0;
	for (signed i = 0; i < n; i ++)
		for (signed j = i + 1; j < n;  j ++)
			for (signed k = j + 1; k < n; k ++)
			{
				int x1 = sqrt((a[i] - a[j]) * (a[i] - a[j]) + (b[i] - b[j]) * (b[i] - b[j]));
				int x2 = sqrt((a[j] - a[k]) * (a[j] - a[k]) + (b[j] - b[k]) * (b[j] - b[k]));
				int x3 = sqrt((a[i] - a[k]) * (a[i] - a[k]) + (b[i] - b[k]) * (b[i] - b[k]));
				if (x1 + x2 > x3 && x1 + x3 > x2 && x2 + x3 > x1)
				{
					if (abs(x1 - x2) < 1e-8 && abs(x2 - x3) < 1e-8 && abs(x1 - x3) < 1e-8) continue;  // 等边三角形不算, 也可以不写, 因为题中要求横纵坐标都是整数, 那么不可能构成等边三角形
					if (abs(x1 - x2) < 1e-8 || abs(x2 - x3) < 1e-8 || abs(x1 - x3) < 1e-8)  // double 类型判断是否相同要用差来判断, double类型的变量在计算机中存储的值会丢失精度, 不能直接用==
						cnt ++;
				}
			}
			
	cout << cnt << endl;
	return 0;
}

ac代码

这题的思路是尽可能优化时间复杂度,

  • 我们枚举每个点, 然后对该点生成一个hash表, 把到该点距离相同的点放到一个数组中, 然后遍历这个hash表中的所有数组,任选数组中的两个点, 判断这三个点是否满足条件

ac代码👇 这个的时间复杂度是在O(n^2) 和 O(n^3)之间的

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define x first
#define y second
typedef pair<int, int> PII;
const double cha = 1e-8;
vector<PII> v;

double dist(int x1, int y1, int x2, int y2)
{
	return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

bool check(PII a, PII b, PII c)
{
	double x1 = dist(a.x, a.y, b.x, b.y);
	double x2 = dist(a.x, a.y, c.x, c.y);
	double x3 = dist(b.x, b.y, c.x, c.y);
	
	if (x1 + x2 <= x3 || x1 + x3 <= x2 || x2 + x3 <= x1) return false;  // 不能构成三角形
	if (abs(x1 - x2) < cha && abs(x1 - x3) < cha && abs(x2 - x3) < cha) return false;  // 是等边三角形。也可以不写, 因为题中要求横纵坐标都是整数, 那么不可能构成等边三角形
	
	return true;
}

signed main()
{
	int n; cin >> n; v.resize(n);
	
	for (int i = 0; i < n; i ++) cin >> v[i].x >> v[i].y;
	
	int cnt = 0;
	
	for (int i = 0; i < n; i ++)
	{
		unordered_map<double, vector<int>> mp;  // 选用i为一个点的前提下, 其他点到i距离相同的点存放到一个 vector中
		for (int j = 0; j < n; j ++)
		{
			if (i == j) continue;
			double dis = dist(v[i].x, v[i].y, v[j].x, v[j].y);  // 计算距离
			mp[dis].emplace_back(j);  
		}
		
		for (auto it : mp)
		{
			vector<int> vv;
			vv = it.second;  // vv 是到i距离相同的点的 集合, 也就是说vv中的元素都是到i的距离相同的点
			for (int j = 0; j < vv.size(); j ++)
				for (int k = j + 1; k < vv.size(); k ++)
				{
					if (check(v[i], v[vv[j]], v[vv[k]])) cnt ++;  // 因为vv里面存的是下标, 所以是 v[vv[j]]
				}
		}
		
	}
	cout << cnt << endl;
	return 0;
}

下面是笔者自己理解的ac代码的时间复杂度的分析

hash时间复杂度分析:

中间的点在执行hash时是最耗时的, 而且图中这种方式的点分布也是让所有点的时间复杂度尽可能多的情况。

下面分别是vector的个数和map个数分析

  • 因为坐标的横纵坐标都只能是整数, 所有一个 map映射的vector中最多有4个数, 也就是说距离到i坐标相同的点最多有4个, 上下左右距离相同 4个, 4个对焦的点距离相同.

  • 而map映射的个数是 中间的点的最外围每增加一圈, map映射的个数加2, 因为每增加一圈 横纵的距离+1, 斜线的距离+根号2, 一共是两种

hash执行总次数 m 和总个数 n 之间的大小关系分析

当点的个数增加到2000的时候, 实际hash执行的次数不到2000 (map的映射个数不到 100,(这里按50个外圈, 50 * 50是2500个点的个数, 比2000个点大), vecotr中最多是4个点, 4 * 4 = 16) 所以hash执行的次数是100 * 16 == 1600, 这还是中间点的情况, 而且是按2500个点算, 其他点的遍历次数更少 ( m < n )

还有就是, 从上面的分析可以看到, 点的个数越小, 遍历hash的总次数有可能反而比 n 次还要多, 但是当点的个数n边大的时候, 遍历hash的总次数会比(n - 1)小很多。------> 比如一共9个点, 3*3, 中间的点正常应该遍历(n - 1) = 8次, 但是用hash的话应该遍历了 2 * (4 * (4 - 1) / 2) = 12次, 2是hash的两个映射 距离为1和距离为根号2, 4是距离为1和根号2的vector中各有4各元素 。(ps:代码中的for ( int j = 0; j < vv.size(); j ++);for (int k = j + 1; k < vv.size(); k ++) 时间复杂度是(n * (n - 1) / 2)

总的时间复杂度

当点的个数比较大的时候, O(n * (n + m)), m < n, 时间复杂度很OK
即使当点的个数n比较小的时候m可能比n大, 但无伤大雅, 因为它不会比n大特别多,而且也说了 n 比较小这个前提, 这个ac代码的时候复杂度可以看成是O(n^2)

觉得写的不错的话, 点个赞吧~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1688628.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Convolutional Occupancy Networks【ECCV2020】

论文&#xff1a;https://arxiv.org/pdf/2003.04618 代码&#xff1a;GitHub - autonomousvision/convolutional_occupancy_networks: [ECCV20] Convolutional Occupancy Networks 图 1&#xff1a;卷积占据网络。传统的隐式模型 (a) 由于其全连接网络结构&#xff0c;表现能力…

【30天精通Prometheus:一站式监控实战指南】第4天:node_exporter从入门到实战:安装、配置详解与生产环境搭建指南,超详细

亲爱的读者们&#x1f44b;   欢迎加入【30天精通Prometheus】专栏&#xff01;&#x1f4da; 在这里&#xff0c;我们将探索Prometheus的强大功能&#xff0c;并将其应用于实际监控中。这个专栏都将为你提供宝贵的实战经验。&#x1f680;   Prometheus是云原生和DevOps的…

4月空调行业线上市场销售数据分析

随着生活品质的提升&#xff0c;消费者对家用空调的诉求不仅仅满足于基本制冷制热功能&#xff0c;而是在环保节能、功能升维、舒适送风、智能科技、焕新设计等多维度提出需求。这种多样化的需求推动了空调产品的创新和升级&#xff0c;这不仅提高了空调的市场竞争力&#xff0…

Linux程序开发(六):进程编程和系统日志守护进程

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

“闻起来有股答辩的味道”,答辩到底是什么味?

“闻起来有股答辩的味道”&#xff0c;答辩到底是什么味&#xff1f; 一位名叫“小鸡全家桶”的作者虚构了这样一个学校故事&#xff0c;故事说&#xff0c;由于学生的考试试卷印刷得特别模糊&#xff0c;导致里面的插图根本看不清&#xff0c;学生感到懵逼&#xff0c;监考老…

oracle主机虚拟内存不足导致实例宕机

检查alert日志&#xff0c;发现pga资源分配时报内存不足&#xff1a; 由于pga内存不足&#xff0c;而导致的数据库宕机。 查看操作系统日志&#xff1a; 发现在宕机之前&#xff0c;出现了虚拟内存不足的情况。 检查确认设置的虚拟内存大小为50多G&#xff1a; 按道理不该出现…

从零开始:Spring Boot项目中如何集成并使用Infinispan

一、介绍 Infinispan 其实就是一个分布式缓存和数据网格平台&#xff0c;提供了高度可扩展和高性能数据缓存解决方案。Infinispan可以作为本地缓存或分布式缓存使用&#xff0c;支持事务、查询、处理大数据等功能。简单地说&#xff0c;Infinispan 可以理解为是 MySQL 的内存版…

玩转OpenHarmony智能家居:如何实现开发版“碰一碰”设备控制

一、简介 “碰一碰”设备控制&#xff0c;依托NFC短距通信协议&#xff0c;通过碰一碰的交互方式&#xff0c;将OpenAtom OpenHarmony&#xff08;简称“OpenHarmony”&#xff09;标准系统设备和全场景设备连接起来&#xff0c;解决了应用与设备之间接续慢、传输难的问题&…

浅析智能体开发(第二部分):智能体设计模式和软件架构

大语言模型&#xff08;LLM&#xff09;驱动的智能体&#xff08;AI Agent&#xff09;展现出许多传统软件所不具备的特征。不仅与传统软件的设计理念、方法、工具和技术栈有显著的差异&#xff0c;AI原生&#xff08;AI Native&#xff09;的智能体还融入了多种新概念和技术。…

springboot-阿里羚羊 服务端埋点

官方文档 集成Java SDK 手动引入jar包「quickaplus-log-collector-java-sdk-1.0.1-SNAPSHOT.jar」 <dependency><groupId>com.alibaba.lingyang</groupId><artifactId>quickaplus-log-collector-java-sdk</artifactId><version>1.0.1&l…

心识宇宙 x TapData:如何加速落地实时数仓,助力 AI 企业智慧决策

使用 TapData&#xff0c;化繁为简&#xff0c;摆脱手动搭建、维护数据管道的诸多烦扰&#xff0c;轻量代替 OGG、DSG 等同步工具&#xff0c;「CDC 流处理 数据集成」组合拳&#xff0c;加速仓内数据流转&#xff0c;帮助企业将真正具有业务价值的数据作用到实处&#xff0c…

Java(十)---抽象类和接口

文章目录 前言知识回顾1.抽象类1.1.抽象类语法1.2 抽象类特性 2.接口2.1.接口的概念2.2 语法规则2.3 接口使用2.4 接口特性2.5 实现多个接口 3.Object类3.1 获取对象信息3.2.对象比较equals方法 4.接口使用实例4.1.Comparable4.2.Comparator4.3.Cloneable深拷贝和浅拷贝 前言 …

CCF-GESP 等级考试 2023年9月认证C++四级真题

2023年9月 一、单选题&#xff08;每题2分&#xff0c;共30分&#xff09; 第 1 题 ⼈们所使⽤的⼿机上安装的App通常指的是&#xff08; &#xff09;。 A. ⼀款操作系统B. ⼀款应⽤软件C. ⼀种通话设备D. 以上都不对 第 2 题 下列流程图的输出结果是&#xff1f;( ) A. 9B.…

2024/5/22 学习杂记

为什么功率放大电路在模电中经常提到&#xff1f; 模拟信号&#xff1a;它是连续变化的电信号&#xff0c;它在时间上和幅度上都是连续的&#xff0c;能够代表信息的连续变化。大多数物理量为模拟信号&#xff0c;如&#xff1a;温度、压力、流量… 非电物理量通过传感器变换成…

RabbitMQ 消息队列安装及入门

市面常见消息队列中间件对比 技术名称吞吐量 /IO/并发时效性&#xff08;类似延迟&#xff09;消息到达时间可用性可靠性优势应用场景activemq万级高高高简单易学中小型企业、项目rabbitmq万级极高&#xff08;微秒&#xff09;高极高生态好&#xff08;基本什么语言都支持&am…

告别付费!这款开源软件让你免费看高清电视直播!

文章目录 📖 介绍 📖🏡 演示环境 🏡📝 开源详情 📝🎯 软件介绍🚀 软件特点🎈 获取方式 🎈⚓️ 相关链接 ⚓️📖 介绍 📖 🔮 揭秘一款神奇的软件,让你轻松畅游电视直播的海洋,无需付费,无需繁琐设置,即可畅享海量高清节目!想要知道它是什么吗?跟…

如何改变echo在Linux下的输出颜色

文章目录 问题回答常规输出字体加粗斜体字带下划线闪烁效果 参考 问题 我正在尝试使用 echo 命令在终端中打印文本。 我想把文本打印成红色。我该怎么做&#xff1f; 回答 你可以使用 ANSI escape codes 定义控制输出颜色的变量。 ANSI escape codes是一种用于在文本中设置…

Gitee在已有项目基础上创建仓库中遇到的问题和解决

问题一&#xff1a;fatal: remote origin already exists 解释&#xff1a;当前仓库添加了一个名为"origin"的远程仓库配置&#xff0c;此时输入 git remote add origin https://xxx就会提示上面的内容。 解决方案1:移除旧的origin git remote remove origin 解决方案…

pyqt6入门案例

效果预览 hello.ui <?xml version"1.0" encoding"UTF-8"?> <ui version"4.0"><class>Dialog</class><widget class"QDialog" name"Dialog"><property name"geometry"><…

2024年5月份最新独角数卡使用USDT详细小白教程

直观配套视频教程 2024年5月份最新独角数卡安装及USDT使用详细小白教程 1、创建服务器 Centos或者Ubuntu2、宝塔面板开心版安装寶塔 Linux 面版 8.0.5 開心版 - 2024年1月12日 - 开心专区 - 异次元 - Powered by Discuz!Centos安装命令&#xff08;默认安装是 8.0.1 直接在线升…