题目链接:https://www.lanqiao.cn/courses/2786/learning/?id=280825
答案:40257
题目解析:
直线分为两部分:平行坐标轴和不平行坐标轴(的直线)
对于平行坐标轴的直线,在结果里加上即可。
对于不平行坐标轴的直线,利用直线的性质:
对于(x1,y1)和(x2,y2),这两点确定的直线y=kx+b,各参数的值为:
k = (y1 - y2) * 1.0 / (x1 - x2) ;(实际操作中需要让 (y1 - y2) 乘上 1.0的目的是使其变为浮点数)
b = y1 * 1.0 - k * x1;
创建一个直线类,根据k和b排序,再根据排序结果进行查重.
注意到,两直线k1,b1和k2,b2为不同直线的充要条件是:
k1 ≠ k2 && b1 ≠ b2
但想在计算机中精确实现上述关系有一定难度,因此结合本题,我们认为:
|a-b|<1e-8 <=> a==b
(本质是因为题目要求的直线中,不同直线k的值或b的值至少相差1e-8以上)
代码:
//#define local
#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
typedef long long ll;
using namespace std;
#define MAXX 20
#define MAXY 21
struct line{
double k,b;
line(double k,double b):k(k),b(b){
}
bool operator < (const line &t) const{
if(k!=t.k)
return k<t.k;
else
return b<t.b;
}
};
//判断double a,b是否相等
bool cheak(double a,double b){
if(fabs(a-b)<1e-8)
return true;
else
return false;
}
vector<line>q;
int main(){
#ifdef local
freopen("data.in","rb",stdin);
//freopen("data.out","wb",stdout);
#endif
int ans=MAXX+MAXY;
for(int i=0;i<MAXX;++i){
for(int j=0;j<MAXY;++j){
for(int w=0;w<MAXX;++w){
if(w==i)
continue;
for(int v=0;v<MAXY;++v){
if(v==j)
continue;
double k=(v-j)*1.0/(w-i);
double b=j*1.0-k*i;
q.push_back(line(k,b));
}
}
}
}
sort(q.begin(),q.end());
ans++;
for(int i=1;i<q.size();++i){
if(cheak(q[i].k,q[i-1].k)&&cheak(q[i].b,q[i-1].b))
continue;
++ans;
}
cout<<ans;
return 0;
}