当前位置:编程学习 > C/C++ >>

hust 1607 Triangles 校赛 一个很好的题 hash

Triangles
Time Limit: 1 Sec  Memory Limit: 128 MB
Submissions: 115  Solved: 30
Description
You are given a figure consisting of n 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 易做图s in the given figure.
Input
There're multiple test cases. In each case:
The first line contains two positive integers n and m. (n <= 200, m <= 20000)
Each of the following n lines contains two real numbers xi and yi  indicating the coordinates of the ith point. (-100000 < xi, yi < 100000)
Each of the following m lines contains four real numbers xi, yi, xj , yj . It means (xi, yi) and (xj , yj) are connected by a segment. We guarantee that these points are part of the given n points.
Output
For each test case, print a single line contains the total number of 易做图s in the given figure. 
Please see sample for more details
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
HINT
Source
The 7th(2012) ACM Programming Contest of HUST
Problem Setter: Zhou Zhou
 
 
 
下面的都是抄袭大神的 莫要鄙视  额先保存下   感觉这个题很好 有必要保存下  
 
 
题意:给一些点的坐标和里面的点构成的一些线段,求这些线段可以构成多少个三角形;
 
思路:因为的点的个数只有100,所以枚举三个点就可以了,O(n^3);
只不过这里有一些条件:这三个点构成的三条线段必须在前面给的线段里,怎么判断呢?
这里我们可以用hash坐标的方法,把一个点的坐标hash成一个数字,这个很简单,就是把
每个点的x,y坐标加上100000,最后key=x*200000+y,因为y不会超过200000,所以
这样就可以保证每个点的坐标不相同了,然后我们再把key和坐标的序号建立一个映射就好了;
再然后我们可以为100点建立一个邻接矩阵,开始输入数据的时候,每来一个线段,我们找到
线段两端的坐标得到它的hash值,并用映射关系找到这个点的序号,然后把邻接矩阵里两个序
号对应的位置赋值为1,例如现在线段两个端点的序号是1和2,map[][]为链接矩阵,那么我们
就令map[1][2]=map[2][1]=1,像加了一条边一样,这样我们就得到了所有点与点之间的关系了;
接下来我们还要解决一个问题,比如线段ab和bc平行,那么我们就又可以得到一条新的线段也就是ac,
解决这个问题我们可以用点疏松的方法,这个类似于floyd算法,时间复杂度O(n^3),具体看
 
 
下面是大神的代码 
 
[cpp]  
#include<math.h>  
#include<stdio.h>  
#include<string.h>  
#include<map>  
using namespace std;  
struct node {double x,y;};  
node point[220];  
double yy[220];  
  
map <double,int > pp ;  
double get(double x,double y) //点hash  
{  
//  x+=100000;  
//  y+=100000;  
    x*=200000;  
    x+=y;  
    return x;  
}  
int mp[220][220];  
  
double dis(node a,node b)  
{  
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));  
}  
int judgeline(node a,node b,node c)//判断线段共线 注意垂直的时候斜率为0  要单独判断啊  
{  
    double x,y,z,t;  
    x=a.x-c.x;  
    y=a.y-c.y;  
    z=b.x-c.x;  
    t=b.y-c.y;  
    if((t<1e-8&&t>-1e-8)&&(y<1e-8&&y>-1e-8))return 1;  
    else  
    {  
        if((t<1e-8&&t>-1e-8)||(y<1e-8&&y>-1e-8))return 0;  
        t=(x/y)-(z/t);  
        return (t<1e-8&&t>-1e-8);  
    }  
}  
int subjudge(node a,node b,node c)//判断三角形  
{  
    double x,y,z;  
    x=dis(a,b);  
    y=dis(a,c);  
    z=dis(b,c);  
    if(x+y-z>1e-8&&x+z-y>1e-8&&y+z-x>1e-8)  
        return 1;  
    else return 0;  
}  
int judge(int a,int b,int c) //判断3个点的关系是否满足  
{  
    if(mp[a][b]&&mp[a][c]&&mp[b][c])  
        return subjudge(point[a],point[b],point[c]);  
    else return 0;  
}  
int main()  
{  
    int n,m,a,b,i,j,k,sum;  
    double x1,y1,x2,y2;  
    while(scanf("%d%d",&n,&m)!=EOF)  
    {  
        pp.clear();  
        for(i=0;i<n;i++)  
        {  
            scanf("%lf%lf",&point[i].x,&point[i].y);  
            yy[i]=get(point[i].x,point[i].y); //点hash  
            pp[yy[i]]=i; //点与序号的映射  
        }  
        memset(mp,0,sizeof(mp));  
        for(i=0;i<m;i++) //建立邻接矩阵  
        {  
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);  
            a=pp[get(x1,y1)];  
            b=pp[get(x2,y2)];  
            mp[a][b]=1;  
            mp[b][a]=1;  
        }  
        for(i=0;i<n;i++) //点疏松  
        {  
            for(j=0;j<n;j++)  
            {  
                if(i!=j)  
                {  
                    for(k=0;k<n;k++)  
                    {  
                        if(i!=k&&i!=j&&j!=k)  
                        {  
                            if
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,