hust 1607 Triangles 校赛 一个很好的题 hash
2012-12-25 00:48
441 查看
Triangles
Time Limit: 1 Sec Memory Limit: 128 MBSubmissions: 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 HUSTProblem 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;
}
相关文章推荐
- qLibc 对于C C++都是一个很好的框架,提供Tree Hash Stack String I/O File Time等功能
- 推荐一个很好的开源的checksum计算工具QuickHash-GUI
- hust 1607--Triangles
- 【计算几何】Triangles HUST 1607
- hust 1607 Triangles(经典好题)
- USCOJ 1231 Triangles(HUST 校赛题)
- 我很好的一个同学,经商的
- 今天看了好多东西,主要发现了一个很好的网站叫慕课网
- 一个很好按键检测程序
- 声卡其实是一个很好的模数转换设备
- 关于一个很好用的数据恢复软件的使用方法
- Hash(篇1)实现一个函数来查找具有相同唯一字符集的所有单词
- 用XMLHTTP很好的一个例子(原创)
- 一个很好的开源图像处理软件--imageJ (2
- 推荐一个很好用的网络U盘(金山快盘),最大容量可以达到5.6G
- 刚发现一个linux在线文档库。很好很强大。
- 推荐一个很好的邮件退信帮助中心的网站
- c++中指针问题一个很好的例子
- Gallery 做的相册 很好的一个学习例子
- 一个很好的 Java 开源网站:open-open