2021蓝桥杯省赛 第三题 直线个数

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;
} 

知乎链接1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值