hdu 5020 Revenge of Collinearity(STL,组合,思路)

10 篇文章 0 订阅
6 篇文章 0 订阅

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.
 

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%.
 

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值