Revenge of Collinearity
Time Limit: 8000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 605 Accepted Submission(s): 204
Problem Description
In geometry, collinearity is a property of a set of points, specifically, the property of lying on a single line. A set of points with this property is said to be collinear (often misspelled as colinear).
---Wikipedia
Today, Collinearity takes revenge on you. Given a set of N points in two-dimensional coordinate system, you have to find how many set of <P i, P j, P k> from these N points are collinear. Note that <P i, P j, P k> cannot contains same point, and <P i, P j, P k> and <P i, P k, P j> are considered as the same set, i.e. the order in the set doesn’t matter.
---Wikipedia
Today, Collinearity takes revenge on you. Given a set of N points in two-dimensional coordinate system, you have to find how many set of <P i, P j, P k> from these N points are collinear. Note that <P i, P j, P k> cannot contains same point, and <P i, P j, P k> and <P i, P k, P j> are considered as the same set, i.e. the order in the set doesn’t matter.
Input
The first line contains a single integer T, indicating the number of test cases.
Each test case begins with an integer N, following N lines, each line contains two integers Xi and Yi, describing a point.
[Technical Specification]
1. 1 <= T <= 33
2. 3 <= N <= 1 000
3. -1 000 000 000 <= Xi, Yi <= 1 000 000 000, and no two points are identical.
4. The ratio of test cases with N > 100 is less than 25%.
Each test case begins with an integer N, following N lines, each line contains two integers Xi and Yi, describing a point.
[Technical Specification]
1. 1 <= T <= 33
2. 3 <= N <= 1 000
3. -1 000 000 000 <= Xi, Yi <= 1 000 000 000, and no two points are identical.
4. The ratio of test cases with N > 100 is less than 25%.
Output
For each query, output the number of three points set which are collinear.
Sample Input
2 3 1 1 2 2 3 3 4 0 0 1 0 0 1 1 1
Sample Output
1 0
思路:自己写的话一点思路都没有,三重循环果然还是炸了。 然后网上看了题解,深感思路巧妙。灵活的运用了map的特性。
枚举三个点之中的第一个点,再枚举第二个点,然后把两点斜率的最简形式存入map中
然后扫一遍map,可以得到多个斜率,每一个斜率个数会有很多个,相当于我们确定于第一个点,现在如果有x个斜率相等,说明有x条线段斜率相同,那么三点共线一共有从x个点中选两个的情况数,即x*(x-1)/2 累加即可得到答案。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
#define N 1010
struct Node
{
int x,y;
} p[N];
typedef pair<int,int> pii;
map<pii,int>mp;
map<pii,int>::iterator it;
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%d %d",&p[i].x,&p[i].y);
int num=0;
for(int i=0;i<n-1;i++)
{
mp.clear();
for(int j=i+1;j<n;j++)
{
int x=p[j].x-p[i].x;
int y=p[j].y-p[i].y;
int t=gcd(x,y);
x/=t;
y/=t;
mp[make_pair(x,y)]++;
}
for(it=mp.begin();it!=mp.end();it++)
if(it->second>=2)
{
int s=it->second;
num+=s*(s-1)/2;
}
}
printf("%d\n",num);
}
return 0;
}