usaco 3.4 Closed Fences 计算几何
2008-08-20 16:58
375 查看
题目给定一个多边形,要求
1)判断是否简单多边形
方法如下
对于临边:假设p1,p2和p2,p3为临边,如果p1,p2,p3重合并且p1,p3在p2的同侧,在存在交叉边,可以通过叉积cross(p1,p2,p3)==0 和点击dot(p1,p2,p3) < 0来判断.
对于不相邻的边:如果规范相交,则存在交叉边.
2)判断观察者是否能看到,题目的意思是只要能看到一点就满足条件,但是如果线段和观察者共线,则不能看到
方法:对于每个顶点p,将其分别做左右微小移动得到点pl,pr, 假设观察者为o,作射线(o,pl)和(o,pr),对于两射线分别求出与其相交并且举例最近的线段,就是能找到观察到的线段
3)输出要求先按第二点排序,再第一点,实际上,只需要把最后一条线段的两点交换顺序,再把最后两条线段交换顺序,输出即可
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
/*
PROG: fence4
LANG: C++
ID: heben991
*/
const int N = 500;
typedef double T;
const T inf = 1e15, eps = 1e-5, pi = acos(-1.0), C = 1e8;
struct point
{
T x, y;
point(T a=0, T b=0)
{
x=a,y=b;
}
}p
, o;
int n;
bool see
;
T dot(point a, point b, point c)
{
return (b.x-a.x)*(c.x-a.x) + (b.y-a.y)*(c.y-a.y);
}
T cross(point a, point b)
{
return a.x*b.y - a.y*b.x;
}
T cross(point a, point b, point c)
{
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
int sign(T x)
{
if( x == 0 ) return 0;
if( x > 0 )return 1;
return -1;
}
bool checkssint(point a, point b, point c, point d)
{
return max(a.x,b.x) > min(c.x,d.x)
&& max(a.y,b.y) > min(c.y,d.y)
&& max(c.x,d.x) > min(a.x,b.x)
&& max(c.y,d.y) > min(a.y,b.y)
&& sign(cross(a,b,c))*sign(cross(a,b,d)) < 0
&& sign(cross(c,d,a))*sign(cross(c,d,b)) < 0;
}
bool segsegint(point p1, point p2, point p3, point p4, point &p)
{
if( !checkssint(p1,p2,p3,p4) ) return 0;
double d, d1, d2;
d = (p1.x-p2.x)*(p4.y-p3.y) - (p1.y-p2.y)*(p4.x-p3.x);
d1 = cross(p3,p4)*(p1.x-p2.x) - cross(p1,p2)*(p3.x-p4.x);
d2 = cross(p1,p2)*(p4.y-p3.y) - cross(p3,p4)*(p2.y-p1.y);
p.x = d1/d;
p.y = d2/d;
return 1;
}
double dist2(point a, point b)
{
return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}
void nearest(T xx, T yy)
{
point pt(xx,yy), inter;
double dt, dm = inf;
int near = -1, i, j, k;
pt.x += (pt.x-o.x)*C;
pt.y += (pt.y-o.y)*C;
for(i = 0; i < n; ++i)
{
if(!segsegint(o,pt,p[i],p[i+1],inter))continue;
dt = dist2(inter, o);
if(dt < dm)
{
dm = dt;
near = i;
}
}
if(near != -1) see[near] = 1;
}
int main()
{
int i, j, k;
freopen("fence4.in", "r", stdin);
freopen("fence4.out","w",stdout);
scanf("%d%lf%lf", &n, &o.x, &o.y);
for(i = 0; i < n; ++i) scanf("%lf%lf", &p[i].x, &p[i].y);
p
= p[0];
p[n+1] = p[1];
for(i = 0; i < n; ++i)
{
if( fabs( cross(p[i],p[i+1],p[i+2]) ) <= eps
&& dot(p[i],p[i+1],p[i+2]) < 0 )
{
printf("---%d/n", i);
break;
}
for(j = i+2; j < n; ++j)
if((j+1)%n != i && checkssint(p[i],p[i+1],p[j],p[j+1]))
{
printf("------%d %d/n", i, j);
break;
}
if(j < n)break;
}
if(i < n)
{
puts("NOFENCE");
return 0;
}
for(i = 0; i < n; ++i)
{
nearest(p[i].x-10.0*eps, p[i].y-pi*eps);
nearest(p[i].x+10.0*eps, p[i].y+10*eps);
}
int cnt = 0;
for(i = 0; i < n; ++i) if(see[i]) ++cnt;
printf("%d/n", cnt);
for(i = 0; i < n-2; ++i)
if(see[i])
{
printf("%.0lf %.0lf %.0lf %.0lf/n",p[i].x,p[i].y,p[i+1].x,p[i+1].y);
}
if(see[i=n-1])
{
printf("%.0lf %.0lf %.0lf %.0lf/n",p[i+1].x,p[i+1].y,p[i].x,p[i].y);
}
if(see[i=n-2])
{
printf("%.0lf %.0lf %.0lf %.0lf/n",p[i].x,p[i].y,p[i+1].x,p[i+1].y);
}
return 0;
}
1)判断是否简单多边形
方法如下
对于临边:假设p1,p2和p2,p3为临边,如果p1,p2,p3重合并且p1,p3在p2的同侧,在存在交叉边,可以通过叉积cross(p1,p2,p3)==0 和点击dot(p1,p2,p3) < 0来判断.
对于不相邻的边:如果规范相交,则存在交叉边.
2)判断观察者是否能看到,题目的意思是只要能看到一点就满足条件,但是如果线段和观察者共线,则不能看到
方法:对于每个顶点p,将其分别做左右微小移动得到点pl,pr, 假设观察者为o,作射线(o,pl)和(o,pr),对于两射线分别求出与其相交并且举例最近的线段,就是能找到观察到的线段
3)输出要求先按第二点排序,再第一点,实际上,只需要把最后一条线段的两点交换顺序,再把最后两条线段交换顺序,输出即可
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
/*
PROG: fence4
LANG: C++
ID: heben991
*/
const int N = 500;
typedef double T;
const T inf = 1e15, eps = 1e-5, pi = acos(-1.0), C = 1e8;
struct point
{
T x, y;
point(T a=0, T b=0)
{
x=a,y=b;
}
}p
, o;
int n;
bool see
;
T dot(point a, point b, point c)
{
return (b.x-a.x)*(c.x-a.x) + (b.y-a.y)*(c.y-a.y);
}
T cross(point a, point b)
{
return a.x*b.y - a.y*b.x;
}
T cross(point a, point b, point c)
{
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
int sign(T x)
{
if( x == 0 ) return 0;
if( x > 0 )return 1;
return -1;
}
bool checkssint(point a, point b, point c, point d)
{
return max(a.x,b.x) > min(c.x,d.x)
&& max(a.y,b.y) > min(c.y,d.y)
&& max(c.x,d.x) > min(a.x,b.x)
&& max(c.y,d.y) > min(a.y,b.y)
&& sign(cross(a,b,c))*sign(cross(a,b,d)) < 0
&& sign(cross(c,d,a))*sign(cross(c,d,b)) < 0;
}
bool segsegint(point p1, point p2, point p3, point p4, point &p)
{
if( !checkssint(p1,p2,p3,p4) ) return 0;
double d, d1, d2;
d = (p1.x-p2.x)*(p4.y-p3.y) - (p1.y-p2.y)*(p4.x-p3.x);
d1 = cross(p3,p4)*(p1.x-p2.x) - cross(p1,p2)*(p3.x-p4.x);
d2 = cross(p1,p2)*(p4.y-p3.y) - cross(p3,p4)*(p2.y-p1.y);
p.x = d1/d;
p.y = d2/d;
return 1;
}
double dist2(point a, point b)
{
return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}
void nearest(T xx, T yy)
{
point pt(xx,yy), inter;
double dt, dm = inf;
int near = -1, i, j, k;
pt.x += (pt.x-o.x)*C;
pt.y += (pt.y-o.y)*C;
for(i = 0; i < n; ++i)
{
if(!segsegint(o,pt,p[i],p[i+1],inter))continue;
dt = dist2(inter, o);
if(dt < dm)
{
dm = dt;
near = i;
}
}
if(near != -1) see[near] = 1;
}
int main()
{
int i, j, k;
freopen("fence4.in", "r", stdin);
freopen("fence4.out","w",stdout);
scanf("%d%lf%lf", &n, &o.x, &o.y);
for(i = 0; i < n; ++i) scanf("%lf%lf", &p[i].x, &p[i].y);
p
= p[0];
p[n+1] = p[1];
for(i = 0; i < n; ++i)
{
if( fabs( cross(p[i],p[i+1],p[i+2]) ) <= eps
&& dot(p[i],p[i+1],p[i+2]) < 0 )
{
printf("---%d/n", i);
break;
}
for(j = i+2; j < n; ++j)
if((j+1)%n != i && checkssint(p[i],p[i+1],p[j],p[j+1]))
{
printf("------%d %d/n", i, j);
break;
}
if(j < n)break;
}
if(i < n)
{
puts("NOFENCE");
return 0;
}
for(i = 0; i < n; ++i)
{
nearest(p[i].x-10.0*eps, p[i].y-pi*eps);
nearest(p[i].x+10.0*eps, p[i].y+10*eps);
}
int cnt = 0;
for(i = 0; i < n; ++i) if(see[i]) ++cnt;
printf("%d/n", cnt);
for(i = 0; i < n-2; ++i)
if(see[i])
{
printf("%.0lf %.0lf %.0lf %.0lf/n",p[i].x,p[i].y,p[i+1].x,p[i+1].y);
}
if(see[i=n-1])
{
printf("%.0lf %.0lf %.0lf %.0lf/n",p[i+1].x,p[i+1].y,p[i].x,p[i].y);
}
if(see[i=n-2])
{
printf("%.0lf %.0lf %.0lf %.0lf/n",p[i].x,p[i].y,p[i+1].x,p[i+1].y);
}
return 0;
}
相关文章推荐
- USACO 3.4 Closed Fences (计算几何)
- USACO6.5-Closed Fences:计算几何
- USACO Section 3.4 Closed Fences - 暴力枚举..
- bzoj1670: [Usaco2006 Oct]Building the Moat护城河的挖掘 计算几何 凸包
- 【bzoj1610】[Usaco2008 Feb]Line连线游戏 计算几何基础
- 【计算几何】【斜率】bzoj1610 [Usaco2008 Feb]Line连线游戏
- [BZOJ1610][Usaco2008 Feb]Line连线游戏(计算几何)
- 3.4 计算几何
- 1914: [Usaco2010 OPen]Triangle Counting 数三角形 (计算几何)
- USACO6.4-Electric Fences:计算几何
- 【BZOJ1580】【USACO2009Hol】杀手游戏 计算几何
- bzoj 1610: [Usaco2008 Feb]Line连线游戏(计算几何)
- 【bzoj1914】[Usaco2010 OPen]Triangle Counting 数三角形 计算几何
- Closed Fences USACO 3.4(阵亡)
- BZOJ_1610_[Usaco2008_Feb]_Line连线游戏_(计算几何基础+暴力)
- bzoj 1573 [Usaco2009 Open]牛绣花cowemb 计算几何 树状数组
- 【BZOJ】 1610 [Usaco2008 Feb]Line连线游戏 计算几何
- 【计算几何】【极角序】【二分】bzoj1914 [Usaco2010 OPen]Triangle Counting 数三角形
- 【计算几何】【凸包】bzoj1670 [Usaco2006 Oct]Building the Moat护城河的挖掘
- 计算几何 usaco Fencing the Cows 圈奶牛