题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上, 那么这些点中任意两点确定的直线是同一条。
给定平面上 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) 之 间的整数的点。
请问这些点一共确定了多少条不同的直线。
实现代码
#include<bits/stdc++.h>
using namespace std;
struct Point
{
double x;
double y; //注意必须是double,如果换成int,后面 int÷int 的时候是取模
}P[25*25];
map<pair<double,double>,int> line; // pair是记录这条直线的 k 和 b,int 是记录这条直线的数据是否出现过
int main()
{
int count=0; // 直线的数量
// col 是说有几列,row 是说有几行
const int col=20; // 横坐标
const int row=21; // 纵坐标
count=20+21;
int cnt=0;
// 把点的数据存进来
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
P[cnt].x=j;
P[cnt].y=i;
cnt++;
}
}
double k=0,b=0;
// 算 k 和 b,查看是否存在相同的直线
for(int i=0;i<cnt;i++)
{
for(int j=0;j<cnt;j++)
{
// 如果选的两个点x或者y相同
if(P[i].x==P[j].x||P[i].y==P[j].y)
{
continue;
}
// 计算斜率 k 和截距 b
k=((P[j].y-P[i].y)/(P[j].x-P[i].x));
b=((P[j].x*P[i].y-P[j].y*P[i].x)/(P[j].x-P[i].x));
if(line[{k,b}]==0)
{
line[{k,b}]=1;
count++;
}
}
}
cout<<count;
return 0;
}
解题思路
一看这个题,脑子里想的首先要找一个东西把直线的斜率和截距存进去,还得记录它是不是之前出现过,这时候就可以用 map<pair<double,double>,int>
来记录直线的信息。然后每个点也写一个结构体,用起来更方便。后面就比较简单了,先把横着的线和竖着的线记录进来,然后只记录斜线。斜线的斜率和截距都用公式算出来存进map,遍历两个点就可以了。
注意点
- 首先注意
map
的用法,很有意义。 - 然后注意后面算截距和斜率都有除的操作,需要用 double 型,不然 int 型的除法其实是取模,会出错。
知识点
map
的用法 C++ map用法struct
的用法 C++ 结构体(struct)最全详解pair
用法 c++STL之pair