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

问题描述

小明在二维坐标系中放置了 ( 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)

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

dubbo复习:(7)使用sentinel对dubbo服务进行限流

一、下载sentinel-dashboard 并启动 java -Dserver.port8080 -Dcsp.sentinel.dashboard.serverlocalhost:8080 -Dproject.namesentinel-dashboard -jar sentinel-dashboard.jar二、在spring boot应用中增加sentinel相关依赖 <dependency><groupId>com.alibaba.csp…

Mybatis Cache(二)MybatisCache+Redis

前面提到了&#xff0c;使用mybatis cache&#xff0c;一般是结合redis使用。 一、demo 1、数据表 create table demo.t_address (id int auto_incrementprimary key,address_name varchar(200) null,address_code varchar(20) null,address_type int n…

Star CCM+在电池热管理中SOC计算、充电Map调用、电池内阻调用的方法

前言 众所周知电池充电电流是随着电池温度与容量变化查表获得(形式见下表),其中电池的充电倍率(电流)是阶梯变化的,而内阻是线型变化的。因此为了仿真的准确定,需要在软件中实现数据的调用,计算电池的发热量。 电池内阻/充电倍率表 一 SOC计算 SOC的估算方法有开路电…

selenium安装出错

selenium安装步骤&#xff08;法1&#xff09;&#xff1a; 安装失败法1 第一次实验&#xff0c;失败 又试了一次&#xff0c;失败 安装法2-失败&#xff1a; ERROR: Could not install packages due to an EnvironmentError: [WinError 5] 拒绝访问。: c:\\programdata\\a…

swust oj 1075: 求最小生成树(Prim算法)

#include <iostream> using namespace std;typedef struct {int n;int e;char data[500];int edge[500][500]; }Graph;typedef struct {int index;int cost; }mincost;typedef struct {int x;//起点int y;//终点int weight;//权重 }EDGE;typedef struct {int index;int …

Bugku Crypto 部分题目简单题解(四)

目录 python_jail 简单的rsa 托马斯.杰斐逊 这不是md5 进制转换 affine Crack it rsa python_jail 启动场景 使用虚拟机nc进行连接 输入print(flag) 发现报错&#xff0c;经过测试只能传入10个字符多了就会报错 利用python中help()函数&#xff0c;借报错信息带出flag变…

2024年商业管理与文化传播国际学术会议(ICBMCC 2024)

2024年商业管理与文化传播国际学术会议&#xff08;ICBMCC 2024) 2024 International Conference on Business Management and Cultural Communication 一、【会议简介】 2024年商业管理与文化传播国际学术会议&#xff08;ICBMCC 2024&#xff09;是一次汇集全球商业管理领域…

SwiftUI中的手势(MagnificationGesture、 RotationGesture)

通过前两篇文章的探索&#xff0c;手势的基本使用规则已经较深的了解&#xff0c;本篇文章主要看看放缩手势MagnificationGesture和旋转手势RotationGesture。 MagnificationGesture 放缩手势 放缩手势在App中用的也比较广泛&#xff0c;下面先看一个示例效果&#xff1a; 上…

必示科技参与智能运维国家标准预研线下编写会议并做主题分享

近日&#xff0c;《信息技术服务 智能运维 第3部分&#xff1a;算法治理》&#xff08;拟定名&#xff09;国家标准预研阶段第一次编写工作会议在杭州举行。本次会议由浙商证券承办。 此次编写有来自银行、证券、保险、通信、高校研究机构、互联网以及技术方等29家单位&#xf…

前端vue 动态加载ts文件,动态调用ts内的方法

业务场景: 在某个业务场景中, 我们需要在数据库配置ts文件路径,和需要调用的函数名称, 前端需要再指定的场景下,触发对应的函数, 并执行处理逻辑,返回结果. 实现: 这是一个数据库配置生成的动态表单 动态校验的例子, 需要引用动态的函数校验 任意一个js文件, common1.ts c…

运算符重载(上)

目录 运算符重载日期类的比较判断日期是否相等判断日期大小 赋值运算符重载赋值运算符重载格式赋值运算符只能重载成类的成员函数不能重载成全局函数用户没有显式实现时&#xff0c;编译器会生成一个默认赋值运算符重载&#xff0c;以值的方式逐字节拷贝 感谢各位大佬对我的支持…

Blender导出fbx模型,导入到ue5中模型丢失纹理材质

UE5系列文章目录 文章目录 UE5系列文章目录前言一、问题原因二、最终效果 前言 Blender导出fbx模型&#xff0c;导入到ue5中&#xff0c;发现模型丢失纹理材质&#xff0c;里面的原神人物模型妮露居然是白模&#xff0c;郁闷了大半天 一、问题原因 我在Blender导出fbx文件时…

如何高效创建与配置工程环境:零基础入门

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、工程环境的搭建与准备 二、配置虚拟环境与选择解释器 三、编写代码与自动添加多行注释 …

Mybatis Cache(一)MybatisCache+Redis

前面提到了&#xff0c;使用mybatis cache&#xff0c;一般是结合redis使用。 一、demo 1、数据表 create table demo.t_address (id int auto_incrementprimary key,address_name varchar(200) null,address_code varchar(20) null,address_type int n…

6.小程序页面布局 - 账单明细

文章目录 1. 6.小程序页面布局 - 账单明细1.1. 竞品1.2. 布局分析1.3. 布局demo1.4. 页面实现-头部1.5. 账单明细1.5.1. 账单明细-竞品分析1.5.2. 账单明细-实现1.5.2.1. 账单明细-实现-mock数据1.5.2.2. 每日收支数据的聚合整理1.5.2.3. 页面scroll-view 1.6. TODO 1. 6.小程序…

雷电预警监控系统:守护安全的重要防线

TH-LD1在自然界中&#xff0c;雷电是一种常见而强大的自然现象。它既有震撼人心的壮观景象&#xff0c;又潜藏着巨大的安全风险。为了有效应对雷电带来的威胁&#xff0c;雷电预警监控系统应运而生&#xff0c;成为现代社会中不可或缺的安全防护工具。 雷电预警监控系统的基本…

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;表现能力…

政策及需求多因素驱动下 中国适老化改造市场空间大

政策及需求多因素驱动下 中国适老化改造市场空间大 适老化改造是为了提高老年人居住环境的舒适度和安全性&#xff0c;满足老年人居住需求进行的建筑改造&#xff0c;根据住房和城乡建设部城市建设司发布的《城市居家适老化改造指导手册》可以将适老化改造分为基础性改造和提升…

Spring Cloud 系列之Gateway:(9)初识网关

传送门 Spring Cloud Alibaba系列之nacos&#xff1a;(1)安装 Spring Cloud Alibaba系列之nacos&#xff1a;(2)单机模式支持mysql Spring Cloud Alibaba系列之nacos&#xff1a;(3)服务注册发现 Spring Cloud 系列之OpenFeign&#xff1a;(4)集成OpenFeign Spring Cloud …

【小笔记】如何在docker中更新或导入neo4j数据?

如何在docker中更新或导入neo4j数据&#xff1f; &#xff08;1&#xff09;背景&#xff1a; 我尝试了4.4.9和5.19.0版本的Neo4j社区版&#xff0c;基于他们的镜像创建容器后&#xff0c;需要导入我准备好的csv文件或dump文件&#xff0c;因为数据量非常大&#xff0c;所以采…