之前做过CAD开发,对向量运算还是挺了解的,不过这题的边界情况害我wa了好多次。
Q1:求线段是否相交,两两枚举,注意重复,可以考虑跨立实验,需要改进的话,可以在跨立实验前加快速排斥实验。
Q2:设观察点为O,取线段AB,及AB中点C,连结AO、BO、CO;
1. 枚举所有线段,若AO、BO与同一条线段相交,则AB看不到。
2. 若A、B很近,则AB可以看成质点,AB看不到。
3. 枚举所有线段,分别与AO、BO、CO求是否相交,循环结束后判断是否有一条线段(AO、BO、CO)没有相交,如果有,则AB可以看见。
4. 二分AB, 对AC、BC进行上述过程。
ps :cross1是端点重合不算相交的运算,cross2是端点重合算相交的运算。
/**//*
ID: lorelei3
TASK: fence4
LANG: C++
*/
#include <fstream>
#include <iostream>
#include <cmath>
using namespace std;
struct Point{
double x,y;
};
struct Segment{
Point start;
Point end;
};
const double ZERO = 1e-5;
Point points[205], ansb[205], anse[205], person;
int n, now;
inline double crossProduct(Point &p1, Point &p2, Point &p3){
return (p1.x-p3.x)*(p2.y-p3.y)-(p2.x-p3.x)*(p1.y-p3.y);
}
bool cross1(Point &p1, Point &p2, Point &p3, Point &p4){
//跨立实验
if(crossProduct(p1, p4, p3)*crossProduct(p4, p2, p3)<=0) return false;
if(crossProduct(p4, p2, p1)*crossProduct(p2, p3, p1)<=0) return false;
return true;
}
bool cross2(Point &p1, Point &p2, Point &p3, Point &p4){
//跨立实验
if(crossProduct(p1, p4, p3)*crossProduct(p4, p2, p3)<0) return false;
if(crossProduct(p4, p2, p1)*crossProduct(p2, p3, p1)<0) return false;
return true;
}
bool can(int k){
for(int i= k+1; i<n; ++i)
if(cross1(points[k], points[k+1], points[i], points[i+1]) )
return false;
return true;
}
bool same(Point &p1, Point &p2){
if(fabs(p1.x-p2.x)<=ZERO && fabs(p1.y-p2.y)<=ZERO )
return true;
return false;
}
bool check(Point &a, Point &b){
int i;
for(i=0; i<n; ++i)
if(i!=now && cross2(person, a, points[i], points[i+1]) && cross2(person,b, points[i], points[i+1]) )
return false;
bool b1=true, b2=true, b3=true;
Point mid;
mid.x = (a.x+b.x)/2;
mid.y = (a.y+b.y)/2;
for(i=0; i<n; ++i){
if(i!=now){
if(b1&&cross2(a, person, points[i], points[i+1])) b1=false;
if(b2&&cross2(b, person, points[i], points[i+1])) b2=false;
if(b3&&cross2(mid, person, points[i], points[i+1])) b3=false;
}
}
if(b1||b2||b3) return true;
if(same(a,b)) return false;
if(check(a, mid)) return true;
if(check(mid, b)) return true;
return false;
}
int main(){
int i;
ifstream fin("fence4.in");
ofstream fout("fence4.out");
fin>>n;
fin>>person.x>>person.y;
for(i=0; i<n; ++i)
fin>>points[i].x>>points[i].y;
points[n]= points[0];
//Q1
for(i=0; i<n; ++i){
if(!can(i)){
fout<<"NOFENCE"<<endl;
return 0;
}
}
//Q2
int cnt=0;
for(i=0; i<n-2; ++i){
now = i;
if(check(points[i], points[i+1])){
ansb[cnt] = points[i];
anse[cnt] = points[i+1];
cnt++;
}
}
now = n-1;
if(check(points[0], points[n-1])){
ansb[cnt] = points[0];
anse[cnt] = points[n-1];
cnt++;
}
now = n-2;
if(check(points[n-2], points[n-1])){
ansb[cnt] = points[n-2];
anse[cnt] = points[n-1];
cnt++;
}
fout<<cnt<<endl;
for(i=0; i<cnt; ++i)
fout<<ansb[i].x<<" "<<ansb[i].y<<" "<<anse[i].x<<" "<<anse[i].y<<endl;
return 0;
}
posted on 2011-01-19 10:46
小阮 阅读(596)
评论(0) 编辑 收藏 引用 所属分类:
USACO