2021蓝桥杯省赛 第三题 直线个数
坑人的点,归根揭底,当x1!=x2&&y1!=y2时,
我们要算出斜率和截距(k,b);在去重时,要考虑double类型的精度缺失问题,不然…return fabs(a - b) < 1e-6; 即如果两个浮点数相差小于某个很小数,就认为它们相等
#include <bits/stdc++.h>
using namespace std;
int M = 20;
int N = 21;
const double pyl = 1e-6;//设置偏移量,精度问题
set<int> set1;
set<int> set2;
double set3[100007][2];
int cc = 0;
void check(int p1,int p2){
int x1,y1,x2,y2;
x1 = p1%M;
if(x1==0){
x1 = M-1;
}
else{
x1 = x1-1;
}
y1 = (p1-1)/M;
x2 = p2%M;
if(x2==0){
x2 = M-1;
}
else{
x2 = x2-1;
}
y2 = (p2-1)/M;
// cout<<x1<<" "<<y1<<"::"<<x2<<" "<<y2<<endl;
if(x1==x2){
set1.insert(x1);
}
else if(y1 == y2){
set2.insert(y1);
}
else if(x1!=x2 && y1!=y2){
int k1 = y2-y1;//斜率分子
int k2 = x2-x1;//斜率分母
int b1 = -x1*(y2-y1)+y1*(x2-x1);//截距分子
int b2 = x2-x1;//截距分母
double k = double(k1)/k2;
double b = double(b1)/b2;
bool f = true;
for(int i=0;i<cc;i++){
if(fabs(k-set3[i][0])<pyl && fabs(b-set3[i][1])<pyl){
f = false;
break;
}
}
if(f){
set3[cc][0]=k;
set3[cc][1]=b;
cc++;
}
}
}
int main(){
int b[500];
for(int i=1;i<=M*N-2;i++){
b[i]=0;
}
b[M*N-1]=1;
b[M*N]=1;
int p1,p2;
bool f = true;
do{
for(int i=1;i<=M*N;i++){
if(b[i]==1 && f){
p1 = i;
f = false;
}
else if(b[i]==1 && !f){
p2 = i;
f = true;
break;
}
}
check(p1,p2);
}while(next_permutation(b+1,b+1+M*N));
cout<<set1.size()+set2.size()+cc<<endl;
return 0;
}
ans = 40257
思路二,用set去重,k用两个数(分子,分母,&& 是gcd后的),b用两个数(分子,分母)。
是将k, b用比值形式将分子分母成对存起来
但是,我写完代码后,发现,答案不对,我也不知道问题在哪,算的是76475。
出错代码如下,请大佬指正!
#include <bits/stdc++.h>
using namespace std;
int M = 20;
int N = 21;
int ans = 0;
set<int> set1;
set<int> set2;
struct edge{
int k1,k2;
int b1,b2;
};
struct cmp{
bool operator()(edge a,edge b){
if(a.k1!=b.k1 || a.k2!=b.k2 || a.b1!=b.b1 || a.b2!=b.b2){
return true;
}
return false;
}
};
set<edge,cmp> set3;
int gcd(int a,int b){
return b ? gcd(b,a%b) : a;
}
void check(int p1,int p2){
int x1,y1,x2,y2;
x1 = p1%M;
if(x1==0){
x1 = M-1;
}
else{
x1 = x1-1;
}
y1 = (p1-1)/M;
x2 = p2%M;
if(x2==0){
x2 = M-1;
}
else{
x2 = x2-1;
}
y2 = (p2-1)/M;
// cout<<x1<<" "<<y1<<"::"<<x2<<" "<<y2<<endl;
if(x1==x2){
set1.insert(x1);
}
else if(y1 == y2){
set2.insert(y1);
}
else if(x1!=x2 && y1!=y2){
int k1 = y2-y1;
int k2 = x2-x1;
int b1 = -x1*(y2-y1)+y1*(x2-x1);
int b2 = x2-x1;
int gcd1 = gcd(k1,k2);
int gcd2 = gcd(b1,b2);
edge t;
t.k1 = k1/gcd1;
t.k2 = k2/gcd1;
t.b1 = b1/gcd2;
t.b2 = b2/gcd2;
set3.insert(t);
}
}
int main(){
int b[500];
for(int i=1;i<=M*N-2;i++){
b[i]=0;
}
b[M*N-1]=1;
b[M*N]=1;
int p1,p2;
bool f = true;
do{
for(int i=1;i<=M*N;i++){
if(b[i]==1 && f){
p1 = i;
f = false;
}
else if(b[i]==1 && !f){
p2 = i;
f = true;
break;
}
}
check(p1,p2);
}while(next_permutation(b+1,b+1+M*N));
cout<<set1.size()+set2.size()+set3.size()<<endl;
// cout<<set1.size()+set2.size()<<endl;
// cout<<set3.size()<<endl;
return 0;
}