【题解】A566.三点共线
题目大意,给定在平面直角坐标系中的多个点,判断有多少个三元组 \((A, B, C)\) 满足共线性质。
题目链接:A566.三点共线。
大题思路就是暴力所有的三元组,判断三个元素的斜率是否相同即可。其实还有其他方法可以做,我个人感觉用斜率法最简单。
有几点需要注意:
在计算斜率的时候,如果多个点处于一个与横坐标轴垂直的线上,那么除以 \(0\) 的时候会爆\(\color{royalblue}\text{RE}\) 需要特判一下。
存储的时候需要使用
double类型。在选取三元组的时候,需要保证不重复不遗漏。不会出现一个点被多次选中,相同的组合被多次计算的情况。
斜率法:
对于三个点 \((x_1, y_1)\), \((x_2, y_2)\), 和 \((x_3, y_3)\),计算任意两点之间的斜率。如果这三个斜率相等,则这三个点共线。但是要注意的是,当两个点的 x 坐标相等时,斜率会无穷大,因此在实际计算中需要特别处理这种情况。
\[\frac{dy}{dx} = \frac{{y_2 - y_1}}{{x_2 - x_1}}
\]
#include <iostream>
using namespace std;
struct point{
int x;
int y;
} arr[105];
int n, cnt = 0;
int main(){
cin >> n;
for (int i=1; i<=n; i++)
cin >> arr[i].x >> arr[i].y;
for (int i=1; i<=n; i++){
for (int j=i+1; j<=n; j++){
for (int k=j+1; k<=n; k++){
int x1 = arr[i].x; int x2 = arr[j].x; int x3 = arr[k].x;
int y1 = arr[i].y; int y2 = arr[j].y; int y3 = arr[k].y;
if (x1 - x2 == 0 && x3 - x2 == 0){
cnt++;
continue;
}
if (x1 - x2 == 0 || x3 - x2 == 0)
continue;
double s1 = 1.0 * (y2 - y1) / (x2 - x1);
double s2 = 1.0 * (y3 - y2) / (x3 - x2);
if (s1 == s2) cnt++;
}
}
}
cout << cnt << endl;
return 0;
}
向量法:
设想将三个点看作向量,即 \(\vec{P_1P_2}\) 和 \(\vec{P_1P_3}\)。如果这两个向量是平行的,则三个点共线。你可以通过计算这两个向量的叉积来验证它们是否平行。如果叉积为零,则两个向量平行,即三个点共线。
\[\text{Cross Product} = \vec{P_1P_2} \times \vec{P_1P_3} = (x_2 - x_1)(y_3 - y_1) - (y_2 - y_1)(x_3 - x_1)
\]
#include <iostream>
using namespace std;
struct point{
int x;
int y;
} arr[105];
int n, cnt;
int main(){
cin >> n;
for (int i=1; i<=n; i++)
cin >> arr[i].x >> arr[i].y;
for (int i=1; i<=n; i++){
for (int j=i+1; j<=n; j++){
for (int k=j+1; k<=n; k++){
int x1 = arr[i].x; int x2 = arr[j].x; int x3 = arr[k].x;
int y1 = arr[i].y; int y2 = arr[j].y; int y3 = arr[k].y;
if ((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1) == 0)
cnt++;
}
}
}
cout << cnt << endl;
return 0;
}
行列式法:
将三个点的坐标表示成矩阵形式,然后计算这个矩阵的行列式。如果行列式的值为零,则表示这三个点共线。有关行列式的计算可以自行在搜索引擎上搜索。
\[\text{Determinant} = \begin{vmatrix} x_1 & y_1 & 1 \\ x_2 & y_2 & 1 \\ x_3 & y_3 & 1 \end{vmatrix} = 0
\]
#include <iostream>
using namespace std;
struct point{
int x;
int y;
} arr[105];
int n, cnt;
int main(){
cin >> n;
for (int i=1; i<=n; i++)
cin >> arr[i].x >> arr[i].y;
for (int i=1; i<=n; i++){
for (int j=i+1; j<=n; j++){
for (int k=j+1; k<=n; k++){
double x1 = arr[i].x; double x2 = arr[j].x; double x3 = arr[k].x;
double y1 = arr[i].y; double y2 = arr[j].y; double y3 = arr[k].y;
if (x1 * y2 + y1 * x3 + x2 * y3 - x1 * y3 - y2 * x3 - x2 * y1 == 0)
cnt++;
}
}
}
cout << cnt << endl;
return 0;
}
面积法:
如果三个点 \(A(x_1, y_1)\), \(B(x_2, y_2)\), 和 \(C(x_3, y_3)\) 共线,则它们构成的三角形的面积为零。
\[S_{area} = \frac{1}{2} |x_1(y_2 - y_3) + x_2(y_3 - y_1) + x_3(y_1 - y_2)|
\]
#include <iostream>
using namespace std;
struct point{
int x;
int y;
} arr[105];
int n, cnt;
int main(){
cin >> n;
for (int i=1; i<=n; i++)
cin >> arr[i].x >> arr[i].y;
for (int i=1; i<=n; i++){
for (int j=i+1; j<=n; j++){
for (int k=j+1; k<=n; k++){
int x1 = arr[i].x; int x2 = arr[j].x; int x3 = arr[k].x;
int y1 = arr[i].y; int y2 = arr[j].y; int y3 = arr[k].y;
if (0.5 * (x1 * (y2 - y3) + x2 * (y3 - y1) + x3*(y1-y2)) == 0)
cnt++;
}
}
}
cout << cnt << endl;
return 0;
}
以上所有代码的时间复杂度为 \(O(n^3)\),其中 \(n\) 是点的数量。但对于本题而言,没有问题不会超时。
【题解】A566.三点共线的更多相关文章
- hdu 4885 (n^2*log(n)推断三点共线建图)+最短路
题意:车从起点出发,每次仅仅能行驶L长度,必需加油到满,每次仅仅能去加油站或目的地方向,路过加油站就必需进去加油,问最小要路过几次加油站. 開始时候直接建图,在范围内就有边1.跑最短了,再读题后发现, ...
- Friends and Berries URAL - 2067 (计算三点共线和计算的时候的注意点)
题目链接:https://cn.vjudge.net/problem/URAL-2067 具体思路:判断三点共线就可以了,只有一对点能满足,如果一对就没有那就没有满足的. 在计算的时候,要注意,如果是 ...
- hdu 4885 (n^2*log(n)判断三点共线建图)+最短路
题意:车从起点出发,每次只能行驶L长度,必需加油到满,每次只能去加油站或目的地方向,路过加油站就必需进去加油,问最小要路过几次加油站. 开始时候直接建图,在范围内就有边1.跑最短了,再读题后发现,若几 ...
- hdu 5020 求三点共线的组合数(容器记录斜率出现次数)
题意: 给你n个点,问你3点共线的组合数有多少,就是有多少种组合是满足3点共线的. 思路: 一开始抱着试1试的态度,暴力了一个O(n^3),结果一如既往的超时了,然后又在刚刚超时 ...
- HDU - 4305 - Lightning 生成树计数 + 叉积判断三点共线
HDU - 4305 题意: 比较裸的一道生成树计数问题,构造Krichhoof矩阵,求解行列式即可.但是这道题还有一个限制,就是给定的坐标中,两点连线中不能有其他的点,否则这两点就不能连接.枚举点, ...
- Leetcode题解(三)
8.String to Integer (atoi) 题目 这道题目关键是要考虑清楚各种输入用例.针对每一种情况,函数都能处理,也就是函数鲁棒性很高.代码如下: class Solution { pu ...
- 2019CSUST集训队选拔赛题解(三)
PY学长的放毒题 Description 下面开始PY的香港之行,PY有n个要去的小吃店,这n个小吃店被m条路径联通起来. PY有1个传送石和n−1个传送石碎片. PY可以用传送石标记一个小吃店作为根 ...
- JSOI Round 2题解
强行一波题解骗一个访问量好了... http://blog.csdn.net/yanqval/article/details/51457302 http://absi2011.is-programme ...
- ZOJ1081:Points Within——题解
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1081 题目大意:给定一个点数为 n 的多边形,点按照顺序给出,再给出 m ...
- AtCoder Grand Contest 039 题解
传送门 \(A\) 首先只有一串的情况下,遇到相同的肯定是改后面那一个最优,然后两串的话可能要分奇偶讨论一下 //quming #include<bits/stdc++.h> #defin ...
随机推荐
- keycloak~网站对接到Keycloak的步骤
新网站对接到KC的部署 kc的环境 向kc申请自己的客户端 kc的登录接口 通过code换token接口 刷新token接口 kc的用户信息接口 kc的jwt token说明 1. kc的环境 测试环 ...
- HarmonyOS系统级推送服务,打造消息通知新体验
8月4日,第五届华为开发者大会 2023(HDC.Together)再次启航.在本次大会上,华为为广大用户带来了HarmonyOS 4全新升级的体验,同时,针对HarmonyOS应用的开发,此次也全面 ...
- 前端vue+elementUI如何实现记住密码功能
我们这回使用纯前端保存密码 既然是记住密码,前端也就是使用cookie保存,访问时用cookie读取 先来了解下cookie的基本使用吧 Cookie 所有的cookie信息都在document.co ...
- Vue 3 进阶用法:异步组件
一.代码分割 一个大型前端应用,如果所有代码都放在单一文件,体积会特别大,下载时间长,白屏时间久,用户体验差. 代码分割是一种有效的优化方式.提前把代码切分为多个小块,只下载当前必需的部分,用到哪块下 ...
- javascript现代编程系列教程之七——字符数据类型-字符集-编码解码-常用字符串处理方法(七)
一.字符集 Unicode:Unicode 是一个字符集(Charset),包含了世界上所有的字符.每个字符在 Unicode 中都有其唯一对应的数字编号,这就是我们常说的 Unicode 码. UT ...
- node统计指定文件夹内代码行数
1. 来源 想对于自己接触前端日常学习与思考的代码行数进行一个统计,看自己大约敲了多少代码 2.代码 const fs = require('fs') const path = require('pa ...
- 【笔记】Oracle union all&for update锁
[笔记]Oracle union all&for update union all 在Oracle中有三种类型的集合操作 UNION:求并,重复记录只显示一次 UNION ALL:求并集,显示 ...
- 力扣697(java)-数组的度(简单)
题目: 给定一个非空且只包含非负数的整数数组 nums,数组的 度 的定义是指数组里任一元素出现频数的最大值. 你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度 ...
- EasyNLP开源|中文NLP+大模型落地,EasyNLP is all you need
简介:EasyNLP背后的技术框架如何设计?未来有哪些规划?今天一起来深入了解. 作者 | 临在.岑鸣.熊兮 来源 | 阿里开发者公众号 一 导读 随着BERT.Megatron.GPT-3等预训练 ...
- EventBridge 集成云服务实践
简介:本篇文章主要向大家分享了通过 EventBridge 如何集成云产品事件源,如何集成云产品事件目标以及通过事件流如何集成消息产品. 作者:李凯(凯易) EvenBridge 集成概述 Even ...