【cdoj 1337】郭大侠与阴阳家 直线平行判断

好吧,和这道题刚了一下午,虽然说很累,但最后A了还是很开心。

一开始自信自己能够A掉这道题,就连续换了几种姿势,写了几份代码,最后还是T了 ,不得不借助标程才发现原来是自己把判断是否平行的条件写复杂了

收获:

1.在判断两直线是否平行的时候,最好采用一次函数,而且并不复杂,虽然计算机有浮点数精度误差,但是对于一般题目还是搓搓有余了。而且每次判断是否相等的时候 用 a-b<1e-6来代替 a==b 保证不坑

2.有时候,得向标程认怂,不为别的,因为从题解还是可以学到很多有用的东西

#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 2020
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
LL n;
struct node{
	LL x, y;
	bool operator < (const node& b) const{
		return x==b.x?y<b.y:x<b.x ;
	}
}nod[maxn];

LL cnt;
struct edge{
	int len;
	double k,b;
	bool operator <(const edge& b)const{
		if(fabs(k-b.k)>1e-6){
			return k<b.k;
		}
		else return len<b.len;
	}
}e[maxn*maxn];

int check(int a,int b){
	return fabs(e[a].k-e[b].k)<1e-6&&e[a].len==e[b].len;
}

int main(){
	scanf("%lld",&n);
	LL x,y;
	for(LL i=1;i<=n;i++){
		scanf("%lld%lld",&x,&y);
		nod[i].x=x;nod[i].y=y;
	}
	sort(nod+1,nod+1+n);
	nod[0].x=-12,nod[0].y=-5;
	int k=0;
	for(int i=1;i<=n;i++){
		if(nod[i].x==nod[k].x&&nod[i].y==nod[k].y )continue;
		nod[++k]=nod[i];
	}
	for(LL i=1;i<=k;i++){
		for(LL j=i+1;j<=k;j++){
			int x=nod[i].x-nod[j].x;
			int y=nod[i].y-nod[j].y ;
			e[++cnt].len=(x*x)+y*y;
			
			if(nod[i].x==nod[j].x){
				e[cnt].k=1e9*1.0;
				e[cnt].b=nod[i].x;
			}
			else {
				e[cnt].k=(nod[i].y-nod[j].y )*1.0/(nod[i].x-nod[j].x)*1.0;
				e[cnt].b=nod[i].y-e[cnt].k*nod[i].x;
			}
			
		}
	}
	LL ans=0;
	sort(e+1,e+1+cnt);
	for(LL i=1;i<=cnt;){	
		int j;
		for(j=i+1;j<=cnt;j++){
			if(!check(i,j))break;
		}
		
		for(int l=i;l<j;l++){
			for(int m=l+1;m<j;m++){
				if(fabs(e[l].b-e[m].b)>1e-6)ans++;
			}
		}
		i=j;
	}
	printf("%lld",ans/2);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值