题目连接
http://acm.xidian.edu.cn/problem.php?id=1153
Description
一天,万神闲着无聊,画了 n 条线段。第 i 条线段有两个端点 (xi0,yi0), (xi1,yi1)。 因为被杜神坑过,万神非常讨厌浮点精度问题,因此这些端点的坐标都是整 数。 万神希望知道,有多少对线段互相平行,或者在同一条直线上(部分或全部 重合也算同一条直线上)
Input
输入包含多组数据,请处理到文件结束。 每组数据,第一行包含一个整数 n。 之后 n 行,每行 4 个整数,表示 xi0,yi0,xi1,yi1。 保证 1 ≤ n ≤ 100000,各个坐标是绝对值在 109 以内的整数。 保证线段的长度不是 0。
Output
对于每组数据输出 1 行,包含 1 个整数,即平行或共线的线段对数。
Sample Input
3
0 0 1 0
1 0 1 1
0 0 1 1
4
0 0 1 1
2 2 3 3
1 2 3 4
2 3 3 3
Sample Output
0
3
Hint
对于第二组样例,第 1 条线段与第 2 条共线,与第 3 条平行,第 2 条线段 与第 3 条平行
题意
找出斜率相同的线段,然后计算可以组合出多少对。
题解
斜率可能出现小数,怕卡精度,就转换成乘法计算y\x < y1\x1 将其转换为y * x1 < x * y1 要注意的是 x1与x可能为负 就要导致变号情况的发生,所以直接全部直接取正值,值得注意,y的正负是不影响符号变化的
代码
#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<string>
#include<cctype>
#include<algorithm>
#include<vector>
#define maxn 1005
#define INF 1e9+7
#define ll long long
#define eps 1e-6
#define maxv 50
using namespace std;
struct qz{
ll x;
ll y;
bool operator < (const qz &a) const {
if(x==0)return false; //x对应的是左值 无穷大情况 直接取返回false
if(a.x==0)return true; // a.x对应右值得比较情况
return y*a.x<a.y*x;
}
bool operator == (const qz &a) const {
if(x==0)return a.x==0;
if(a.x==0)return false;
return y*a.x==a.y*x;
}
};
qz a[100005];
int main(){
int n;
while(scanf("%d",&n)!=EOF){
for(int i=0; i<n;i++){
ll x,y,xx,yy;
scanf("%lld%lld%lld%lld",&x,&y,&xx,&yy);
a[i].x=x-xx;
a[i].y=y-yy;
if(a[i].x<0){
a[i].x=-a[i].x;
a[i].y=-a[i].y;
}
}
ll ans=0;
ll ant=1;
sort(a,a+n);
for(int i=0;i<n-1;i++){
if(a[i]==a[i+1])ant++;
else{
ans+=(ant-1)*ant/2;
ant=1;
}
}
if(a[n-1]==a[n-2])ans+=(ant-1)*ant/2;
printf("%lld\n",ans);
}
return 0;
}
GET
- 重载运算符真的好神奇,真的又学到了很多