您的位置:首页 > 其它

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

2012-12-25 00:48 441 查看

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 triangles 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 triangles 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),具体看

下面是大神的代码 

#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(!mp[j][k]&&mp[i][j]&&mp[i][k]&&judgeline(point[i],point[j],point[k]))
mp[j][k]=1,mp[k][j]=1;
}
}
}
}
}
sum=0;
for(i=0;i<n;i++) //三角形枚举并判断
for(j=i+1;j<n;j++)
for(k=j+1;k<n;k++)
sum+=judge(i,j,k);
printf("%d\n",sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: