【题解】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 ...
随机推荐
- SAST-数据流分析方法-理论
引言 众所周知,数据流分析是实现污点分析的一种常用技术 数据流分析分为过程内的数据流分析与过程间的数据流分析.前者是对一个方法体内的数据流分析,主要是基于CFG分析,不涉及方法调用:后者是基于不同方法 ...
- innoSetup打包文件编写模板
现在打包主要是使用 innosetup 这个软件来进行打包,支持录制脚本和手动编写脚本,比较好用. 此文章主要记录手写脚本,便于后期查询,借鉴. 文档: inno setup :https://blo ...
- 在HarmonyOS上使用ArkUI实现计步器应用
介绍 本篇Codelab使用ArkTS语言实现计步器应用,应用主要包括计步传感器.定位服务和后台任务功能: 1. 通过订阅计步器传感器获取计步器数据,处理后显示. 2. 通过订阅位置服务获取位 ...
- 94个JS/eTS开源组件首发上新,肯定有你要用的一款!
原文:https://mp.weixin.qq.com/s/6RdxNisTQoyPds811PNZKA,点击链接查看更多技术内容. 2021年的华为开发者大会(HDC2021)上,我们发布了新一代的 ...
- CS101
Turing machine:图灵机 理论上可以计算任何东西 CPU(Center Process Unit):中央处理器 是现代电脑的"大脑",其中包含数十亿细小开关的硅片,即晶 ...
- Matplotlib Installing an official release from resources 源码安装Matplotlib官方版本
Installation Installing an official release Matplotlib releases are available as wheel packages for ...
- 把vim配置成顺手的python轻量级IDE(一)
把vim配置成顺手的python轻量级IDE(一) 地球的外星人君 Linux云计算和Python推动市场提升的学习研究者. 分享一篇文章,正好最近正在折腾VIM,原文在把vim配置成顺手的pytho ...
- MUI-拿到版本名称和版本code
场景: 一般App发布了新版本之后,都会提示用户去更新.这就需要我们获取App的当前版本号与后台存储的版本号做对比来判断是否需要更新. 获取版本名称和版本code: 打开manifest.json文件 ...
- Spark3.0 Standalone模式部署
之前介绍过Spark 1.6版本的部署,现在最新版本的spark为3.0.1并且已经完全兼容hadoop 3.x,同样仍然支持RDD与DataFrame两套API,这篇文章就主要介绍一下基于Hadoo ...
- 力扣636(java)-函数的独占时间(中等)
题目: 有一个 单线程 CPU 正在运行一个含有 n 道函数的程序.每道函数都有一个位于 0 和 n-1 之间的唯一标识符. 函数调用 存储在一个 调用栈 上 :当一个函数调用开始时,它的标识符将会 ...