题目
题目描述:
在平面直角坐标系中,两点可以确定一条直线。
如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。
给定平面上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) 之间的整数的点。
请问这些点一共确定了多少条不同的直线。
解题思路
主体
- 建立坐标系
- 考虑每条直线的斜率和截距
筛选
- 先把每条直线的斜率和截距记录下来,在进行判重,因为截距是浮点数,所以判重需要注意
方法
- 先排序,按照斜率优先,斜率相等排截距
- 排完后比较前后两个元素,如果元素斜率不等,就加一条直线,如果斜率相等后截距不等,也加一条直线
- 不能用0判断,因为是浮点数,可能不等于0,考虑极值1e-8进行比较差值绝对值
#include<bits/stdc++.h>
using namespace std;
struct zhixian //记录
{
double k;
double b;
}a[500000];
bool cmp(zhixian q,zhixian w) //排序
{
if(q.k!=w.k)
return q.k>w.k;
else
return q.b>w.b;
}
int main(){
int temp=0;
for(int x1=0;x1<20;x1++) //遍历每个点
for(int y1=0;y1<21;y1++)
for(int x2=0;x2<20;x2++)
for(int y2=0;y2<21;y2++)
{
if(x1!=x2) //分母不为零,垂直另算
{
double k=(double)(y2-y1)/(x2-x1);
double b=(double)(y2-x2*k);
//a[temp].k=k;
//a[temp++].b=b;
a[temp++]={k,b} ;
}
}
int ans=0;
sort(a,a+temp,cmp);
for(int i=0;i<temp;i++)
if(fabs(a[i].k-a[i+1].k)>1e-8||fabs(a[i].b-a[i+1].b)>1e-8)
ans++;
ans+=20; //垂直的有20条
cout<<ans<<endl;
return 0;
}
不懂私信或评论