题目描述
在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上, 那么这些点中任意两点确定的直线是同一条。
给定平面上 2 × 3 个整点(x,y)∣0≤x<2,0≤y<3,x∈Z,y∈Z,即横坐标 是 0 到 1 (包含 0 和 1) 之间的整数、纵坐标是 0 到 2 (包含 0 和 2) 之间的整数 的点。这些点一共确定了 11 条不同的直线。
给定平面上 20×21 个整点 (x,y)∣0≤x<20,0≤y<21,x∈Z,y∈Z,即横 坐标是 0 到 19 (包含 0 和 19) 之间的整数、纵坐标是 0 到 20 (包含 0 和 20) 之 间的整数的点。
请问这些点一共确定了多少条不同的直线。
set
:
set
是 C++ 标准库中的一种关联容器,用于存储唯一元素(不允许重复)。元素会自动按升序排序(默认使用
<
运算符比较)。
pair<double, double>
:
pair
是 C++ 标准库中的一个模板类,用于存储两个值(键值对)。这里的
pair<double, double>
表示一个包含两个double
类型值的对。
set<pair<double, double>> s;
:
定义了一个名为
s
的集合,集合中的每个元素是一个pair<double, double>
类型。例如,
s
可以存储{(1.0, 2.0), (3.5, 4.5), (0.0, 0.0)}
这样的数据。
保证直线的唯一性:
已知直线的斜率 k 和 y 截距 b 的情况。
y=kx+b
-
k:直线的斜率(表示直线的倾斜程度)。
-
b:直线与 y 轴的交点(y 截距)。
枚举出{k, b}
当x1=x2时,b=0,所以单独算出b=0(垂直于x轴时)的情况,20种
#include<iostream>
#include<set>
#include<utility> // for pair
using namespace std;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
//定义了一个名为 s 的集合(set),其中每个元素是一个 pair<double, double> 类型
//使用set对{k, b}数据对去重
set<pair<double, double>> s;
//枚举第一个坐标点
for(int x1=0; x1<20; ++x1)
{
for(int y1=0; y1<21; ++y1)
{
//枚举第二个坐标点
for(int x2=x1+1; x2<20; ++x2)
{
for(int y2=0; y2<21; ++y2)
{
double k = (double)(y2-y1) / (x2-x1);
//这里如果用这个式子,先算除法再算乘法,精度误差会进一步扩大,通分
//double b = (double)(y1-(y2-y1) / (x2-x1)*x1);
double b = (double)(y1*x2-y2*x1)/(x2-x1);
s.insert({k, b});
}
}
}
}
cout<<s.size() + 20;
return 0;
}