ZJU2102 Tables - 计算几何 线段与圆相交
2008-03-28 18:14
447 查看
题目大意:
输入n个圆形桌子的圆心和半径(从俯视的角度看),给出一根木棍两端点的坐标,问木棍会不会掉到地上。(n<=10000)假设桌子完全水平,木棍的质量分布均匀。
分析:
设木棍端点为a,b,因为木棍质量分布均匀,所以重心c一定在(a+b)/2处。
1、若重心c点被包放在任何一个桌子上,则木棍不会掉;
2、否则,若重心c两侧分别有一部分放在桌子上,木棍也不会掉。
第一种情况需要判断点是否在圆内,很简单,判断点c到圆心的距离小于等于半径即可。
第二种情况是要分别判断线段ac,cb是否与圆相交,其核心也就是计算圆心到线段的距离。
下面分析如何计算点到线段距离:
假设线段端点为ab,点为p。过p作直线ab的垂线。
1、若ab在垂线同侧,那么距离就是p到直线ab的距离。
2、若ab在垂线两侧,那么距离就是p到最近一个端点的距离。
判断ab在同侧还是异侧可以用向量点乘,pa·pb < 0 异侧; >=0 同侧。
计算点p到直线ab的距离可用向量叉乘,d = (ab×ap) / |ab|。
==================================================
/*
ZJU2102 Tables
*/
#include <stdio.h>
#include <math.h>
#define N 10005
typedef struct{
double x,y;
}Point;
double r
;
Point p
;
Point a,b,c;
double dis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double dot(Point p1,Point p2,Point p0){
return (p1.x-p0.x)*(p2.x-p0.x) + (p1.y-p0.y)*(p2.y-p0.y);
}
double mul(Point p1,Point p2,Point p0){
return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
}
double Min(double a,double b){
return a>b?b:a;
}
double Abs(double a){
return a>0?a:-a;
}
double disline(Point a,Point b,Point p){
if(dot(a,b,p)<0) return Abs(mul(b,p,a))/dis(a,b);
else return Min(dis(a,p),dis(b,p));
}
int main()
{
int i,j,n;
int flag,fl,fr;
while(scanf("%d",&n),n){
//input
for(i=0;i<n;i++)
scanf("%lf%lf%lf",&p[i].x,&p[i].y,&r[i]);
scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
c.x=(a.x+b.x)/2.;
c.y=(a.y+b.y)/2.;
//judge
flag=fr=fl=0;
for(i=n-1;i>=0&&!flag;i--){
if(dis(c,p[i])<=r[i]) flag=1;
else if(disline(a,c,p[i])<=r[i]) fl=1;
else if(disline(c,b,p[i])<=r[i]) fr=1;
if(fl&&fr) flag=1;
}
//output
if(flag) puts("STAY");
else puts("FALL");
}
return 0;
}
输入n个圆形桌子的圆心和半径(从俯视的角度看),给出一根木棍两端点的坐标,问木棍会不会掉到地上。(n<=10000)假设桌子完全水平,木棍的质量分布均匀。
分析:
设木棍端点为a,b,因为木棍质量分布均匀,所以重心c一定在(a+b)/2处。
1、若重心c点被包放在任何一个桌子上,则木棍不会掉;
2、否则,若重心c两侧分别有一部分放在桌子上,木棍也不会掉。
第一种情况需要判断点是否在圆内,很简单,判断点c到圆心的距离小于等于半径即可。
第二种情况是要分别判断线段ac,cb是否与圆相交,其核心也就是计算圆心到线段的距离。
下面分析如何计算点到线段距离:
假设线段端点为ab,点为p。过p作直线ab的垂线。
1、若ab在垂线同侧,那么距离就是p到直线ab的距离。
2、若ab在垂线两侧,那么距离就是p到最近一个端点的距离。
判断ab在同侧还是异侧可以用向量点乘,pa·pb < 0 异侧; >=0 同侧。
计算点p到直线ab的距离可用向量叉乘,d = (ab×ap) / |ab|。
==================================================
/*
ZJU2102 Tables
*/
#include <stdio.h>
#include <math.h>
#define N 10005
typedef struct{
double x,y;
}Point;
double r
;
Point p
;
Point a,b,c;
double dis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double dot(Point p1,Point p2,Point p0){
return (p1.x-p0.x)*(p2.x-p0.x) + (p1.y-p0.y)*(p2.y-p0.y);
}
double mul(Point p1,Point p2,Point p0){
return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
}
double Min(double a,double b){
return a>b?b:a;
}
double Abs(double a){
return a>0?a:-a;
}
double disline(Point a,Point b,Point p){
if(dot(a,b,p)<0) return Abs(mul(b,p,a))/dis(a,b);
else return Min(dis(a,p),dis(b,p));
}
int main()
{
int i,j,n;
int flag,fl,fr;
while(scanf("%d",&n),n){
//input
for(i=0;i<n;i++)
scanf("%lf%lf%lf",&p[i].x,&p[i].y,&r[i]);
scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
c.x=(a.x+b.x)/2.;
c.y=(a.y+b.y)/2.;
//judge
flag=fr=fl=0;
for(i=n-1;i>=0&&!flag;i--){
if(dis(c,p[i])<=r[i]) flag=1;
else if(disline(a,c,p[i])<=r[i]) fl=1;
else if(disline(c,b,p[i])<=r[i]) fr=1;
if(fl&&fr) flag=1;
}
//output
if(flag) puts("STAY");
else puts("FALL");
}
return 0;
}
相关文章推荐
- poj 3565(计算几何,线段相交)
- 移动微小的距离,线段相交,计算几何(怪物陷阱,LA 2797)
- 计算几何:线段相交(迷宫寻宝)
- 计算几何---判断线段相交(二)
- POJ 2653 Pick-up sticks(计算几何,判断线段相交)
- nod1264 线段相交(计算几何)
- POJ 1127 基础计算几何(判断两线段相交)+并查集
- POJ 1556 计算几何 判断线段相交 最短路
- 计算几何之线段相交问题模板
- 计算几何--判断线段是否相交
- POJ 3304 计算几何 直线与线段相交
- POJ 1127-Jack Straws(计算几何 线段相交)
- COJ 1645计算几何:判断线段是否相交
- POJ 3304 Segments (计算几何、判断直线与线段是否相交)
- 【计算几何】 POJ 1127 Jack Straws 判断线段是否相交
- POJ 2318 TOYS 计算几何 线段相交
- 【计算几何】判断线段相交
- 计算几何之判断线段相交
- 【计算几何初步-线段相交+并查集】【HDU1558】Segment set
- HDU1147 - Pick-up sticks - 计算几何(判断线段相交)