【蓝桥杯·直线】集合妙用

本题可以从直线一般式入手 Ax+By+C=0 , 即:

(y1-y2) * x +(x2-x1) * y +( x1 * y2 - x2 * y1)=0 

考虑到A、B、C可能成倍数关系,但它们是一条直线,只记录一次,因此用__gcd(x,y)函数求出A、B、C三者的最大公因数并相除。

考虑到直线会有重复的情况,因此选用集合set储存A、B、C。set 是一个有序的容器,里面的元素都是排序好的,支持插入,删除,查找等操作,就像一个集合一样。set 插入的元素不能相同,且set 中的元素不像 map 那样可以同时拥有实值(value)和键值(key),只能存储键,是单纯的键的集合,因此用pair中套pair的形式{{A,B}C}来存储键值,最后返回集合大小即为直线数。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
using namespace std;

typedef pair<int,int> PII;
typedef pair<PII,int> PIII;
vector<PII> v;
set<PIII> s;
int x,y;

int main(){
	cin>>x>>y;
	
	for(int i=0;i<x;i++){
		for(int j=0;j<y;j++){
			v.push_back({i,j});
		
		}//for2
		
	}//for1
	
	
	int x1,y1,x2,y2,A,B,C,ggcd;
	for(int i=0;i<v.size();i++){
		for(int j=i+1;j<v.size();j++){
			x1=v[i].first;
			y1=v[i].second;
			x2=v[j].first;
			y2=v[j].second;
			A=x1-x2;
			B=y1-y2;
			C=x2*y1-x1*y2;
			
			ggcd=__gcd(__gcd(A,B),C);
		
			A=A/ggcd, B=B/ggcd, C=C/ggcd;
		
			s.insert({{A,B},C});
			
			
		}//for2
		
	}//for1
	
	cout<<s.size()<<endl;
	
	return 0;
} //main

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值