【题解】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 ...
随机推荐
- springboot整合redis之发送手机验证码
阿里云服务发送手机短信验证码-----(第二篇) 文章概述:springboot整合redis之发送手机验证码注册登录 注:搭建springboot项目可以参考这篇文章: 前言:短信验证码是通过发送验 ...
- Linux-主机之间创建免密
一.四台主机进行免密 192.168.10.6 192.168.10.11 192.168.10.12 192.168.10.13 二.192.168.10.6主机生成密钥对,并将公钥传输到其它所有主 ...
- 重新点亮shell————测试命令[六]
前言 我们写好脚本之后希望有一个测试. 正文 介绍一下exit,如果exit 0,那么表示正常退出. 如果exit 10,也就是非0,那么就是异常退出. 然后这个test 标准为[]和 [[]]这样子 ...
- 基于Material Design风格开源、易用、强大的WPF UI控件库
前言 今天大姚给大家分享一款基于Material Design风格开源.免费(MIT License).易于使用.强大的WPF UI控件库:MaterialDesignInXamlToolkit. 项 ...
- MRBS(Meeting Room Booking System)开源的会议室预订系统搭建使用
前一家公司所有的办公系统都是自己开发的,包括排班.工单.会议室预定等等,很方便. 目前所在的公司,每周部门例会找行政预订了会议室,但多次去都被人占了,很烦,于是网上找了一个评价不错的系统,python ...
- tensorflow的variable、variable_scope和get_variable的用法和区别
在tensorflow中,可以使用tf.Variable来创建一个变量,也可以使用tf.get_variable来创建一个变量,但是在一个模型需要使用其他模型的变量时,tf.get_variable就 ...
- 《c#高级编程》第3章C#3.0中的更改(五)——扩展方法
C#扩展方法是一种语法,可以为已有的类添加新的实例方法,而无需修改原来的类定义.它的语法形式为: ```csharppublic static void MyExtensionMethod(this ...
- vue 商品sku添加,笛卡尔算法,商品添加。动态生成table,table添加值后 再生成的table 不改变table之前输入的值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 怀里橘猫柴犬,掌上代码江湖——对话阿里云 MVP郭旭东
简介: 跟郭旭东聊过之后,我对程序员的敬佩又多一分.这个92年的开发者,难能可贵地兼备朝气蓬勃的技术能量与长远深刻的行业洞见.独自承担DevOps平台从0到1的所有工作,我打趣说超级开发者不过如此,他 ...
- 国内唯一连续入选Gartner,Quick BI是如何做到的?
简介:阿里云Quick BI凭借灵活的公共云部署,私有化独立部署能力.无缝对接各类云上数据库和自建数据库.可视化搭建分析.高效数据处理能力与强大数据计算能力,使得在2022年持续入选Gartner ...