Triangles

1010: Triangles

Time Limit: 2 Sec  Memory Limit: 128 MB
Submit: 18  Solved: 8

Description

You are given a figure consisting of points in a 2D-plane and m segments connecting some of them. We guarantee that any two segments don’t share points except their ends and there’s no more than one segment between the same pair of points. Please count the total number of triangles in the given figure. 

Input

There’re multiple test cases. In each case:
The first line contains two positive integers 
and m. (≤ 200, ≤ 20000)

Each of the following lines contains two real numbers xand yindicating the coordinates of the i-th point. (100000 < xi, y100000)

Each of the following m lines contains four real numbers xiyixjy. It means (xi,yi) and (xj,yj) are connected by a segment. We guarantee that these points are part of the given points. 

Output

For each test case, print a single line contains the total number of triangles in the given figure. 

Sample Input

4 5
0 0
1 1
2 0
1 0
0 0 1 1
1 1 2 0
2 0 1 0
1 0 0 0
1 1 1 0

Sample Output

3

思路:题意是给你n个点,在这n个点里有m条连线,求这些线段最后组成多少个三角形。题目想好怎么做就不难了,大致就是先找出:三点在一条线上,但是只有两条连线,你必须找出这样的例子,并且把第三条线段加上,然后就是遍历所有的点,三点之间有连线且不共线,则组成三角形。
代码:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<map>
#include<cstring>
using namespace std;
const unsigned int MAX=200;
#define ERR 0.000001
struct Point
{
    double x,y;
}point[MAX+10];
int edge[MAX+10][MAX+10];
map <double,int> mymap;
bool in_line(Point a1,Point a2,Point a3)//判断是否共线
{
     if(fabs((a2.x-a1.x)*(a3.y-a2.y)-(a2.y-a1.y)*(a3.x-a2.x))<=ERR)
        return true;
     return false;
}
int main()
{
    //freopen("Triangles.in","r",stdin);
    int m,n,i,j,k,ans;
    int u,v;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        mymap.clear();
        memset(edge,0,sizeof(edge));
        ans=0;
        for(i=0;i<n;i++)
        {
            scanf("%lf%lf",&point[i].x,&point[i].y);
            mymap[point[i].x*20000+point[i].y]=i;
        }
        for(i=0;i<m;i++)
        {
            double p1,q1,p2,q2;
            scanf("%lf%lf%lf%lf",&p1,&q1,&p2,&q2);
            u=mymap[p1*20000+q1];
            v=mymap[p2*20000+q2];
            //printf("u==%d  v==%d\n",u,v);
            edge[u][v]=edge[v][u]=1;//点与线之间联系起来
        }
        /*for(i=0;i<n;i++)
        {
            for(j=i+1;j<n;j++)
            {
                printf("edge[%d][%d]=%d  ",i,j,edge[i][j]);
            }
            printf("\n");
        }*/
        for(i=0;i<n;i++)
            for(j=0;j<n;j++)
                for(k=0;k<n;k++)
                    if(i!=j&&j!=k&&i!=k&&edge[j][i]&&edge[i][k]&&!edge[j][k]&&in_line(point[i],point[j],point[k]))
                        edge[j][k]=edge[k][j]=1;//三个点中,有两条连线,并且三点共线,加一条连线
        /*for(i=0;i<n;i++)//这种方法貌似可以,并且复杂度较低,但就是通不过,不知为啥
            for(j=i+1;j<n;j++)
                for(k=j+1;k<n;k++)
                {
                    //printf("point[%d] x=%lf  y=%lf   ",i,point[i].x,point[i].y);
                    //printf("point[%d] x=%lf  y=%lf   ",j,point[j].x,point[j].y);
                    //printf("point[%d] x=%lf  y=%lf   \n",k,point[k].x,point[k].y);
                    if(in_line(point[i],point[j],point[k]))
                    {
                        if((edge[i][j]&&(edge[j][k]||edge[i][k]))||(edge[j][k]&&edge[i][k]))
                            edge[i][j]=edge[i][k]=edge[j][k]=edge[j][i]=edge[k][i]=edge[k][j]=1;
                    }
                }*/
        for(i=0;i<n;i++)//扫描所有点,三点两两之间有连线,且不共线,则组成三角形
            for(j=i+1;j<n;j++)
                for(k=j+1;k<n;k++)
                {
                    if(edge[i][j]&&edge[i][k]&&edge[j][k]&&!in_line(point[i],point[j],point[k]))
                        ans++;
                }
        printf("%d\n",ans);
    }
    return 0;
}

FROM:暑假训练第二场
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值