http://hihocoder.com/contest/icpcbeijing2017/problem/7
bfs+计算几何
难点是线段与三角形的关系,有3种情况 1. 线段2端点都在三角形外,判断线段与三角形3条边是否规范相交 2.线段一个端点在三角形内或上,另一个在三角形外,两个点靠近一点点,再判是否在三角形内3.两个点都在三角形内或上,看中点是否在三角形内
计算几何还是菜啊
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pi;
const int maxn = 29;
char mapp[maxn][maxn];
int dir[8][2] = {1,0,-1,0,0,1,0,-1,1,1,1,-1,-1,1,-1,-1};
int n;
const double eps = 1e-6;
struct Point{
double x,y;
Point operator -(const Point&a){
return {x-a.x,y-a.y};
}
Point operator +(const Point&a){
return {x+a.x,y+a.y};
}
double operator *(const Point&a){
return x*a.x+y*a.y;
}
Point operator *(const double &a){
return {x*a,y*a};
}
double operator ^(const Point&a){
return x*a.y-y*a.x;
}
};
int sig(double x){
if(fabs(x)<eps) return 0;
return x<0?-1:1;
}
double multi(Point p1,Point p2,Point base){
Point v1 = p1-base;
Point v2 = p2-base;
return v1^v2;
}
bool onseg(Point a,Point b,Point now){
if(now.x<=max(a.x,b.x) && now.x>=min(a.x,b.x) && now.y<=max(a.y,b.y)
&& now.y>=min(a.y,b.y) && sig(multi(b,now,a))==0) return true;
return false;
}
bool intrangle(Point a,Point b,Point c,Point now){
int sig1 = sig(multi(now,b,a));
int sig2 = sig(multi(now,c,b));
int sig3 = sig(multi(now,a,c));
if(sig1==1 && sig2==1 && sig3==1) return true;
if(sig1==-1 && sig2==-1 && sig3==-1) return true;
return false;
}
bool intrangleOrOnSeg(Point a,Point b,Point c,Point now){
int sig1 = sig(multi(now,b,a));
int sig2 = sig(multi(now,c,b));
int sig3 = sig(multi(now,a,c));
if(sig1==1 && sig2==1 && sig3==1) return true;
if(sig1==-1 && sig2==-1 && sig3==-1) return true;
if(onseg(a,b,now)) return true;
if(onseg(c,b,now)) return true;
if(onseg(a,c,now)) return true;
return false;
}
Point trangle[10];
int vis[maxn][maxn];
int step[maxn][maxn];
queue<pi> q;
bool kp(Point a,Point b,Point c,Point d){
if(min(a.x,b.x)<=max(c.x,d.x) &&
min(c.x,d.x)<=max(a.x,b.x) &&
min(a.y,b.y)<=max(c.y,d.y) &&
min(c.y,d.y)<=max(a.y,b.y) ) return true;
return false;
}
bool kl(Point a,Point b,Point c,Point d){
double tv1 = multi(c,d,a);
double tv2 = multi(c,d,b);
double tv3 = multi(a,b,c);
double tv4 = multi(a,b,d);
if(sig(tv1*tv2)<0 && sig(tv3*tv4)<0) return true;
return false;
}
bool gfxj(Point a,Point b,Point c,Point d){
if(kp(a,b,c,d) && kl(a,b,c,d)) return true;
return false;
}
Point mov(Point base,Point vec,double ra){
Point tmp = vec*ra;
return base+tmp;
}
bool check(Point la,Point lb){
int in = 0;
if(intrangleOrOnSeg(trangle[0],trangle[1],trangle[2],la)) in++;
if(intrangleOrOnSeg(trangle[0],trangle[1],trangle[2],lb)) in++;
if(in==0) {
if(gfxj(trangle[0],trangle[1],la,lb)) return true;
if(gfxj(trangle[2],trangle[1],la,lb)) return true;
if(gfxj(trangle[0],trangle[2],la,lb)) return true;
return false;
}else if(in==2){
Point mid = {(la.x+lb.x)/2,(la.y+lb.y)/2};
if(intrangle(trangle[0],trangle[1],trangle[2],mid)) return true;
return false;
}else{
Point tmp1 = mov(la,lb-la,0.01);
Point tmp2 = mov(lb,la-lb,0.01);
if(intrangle(trangle[0],trangle[1],trangle[2],tmp1))return true;
if(intrangle(trangle[0],trangle[1],trangle[2],tmp2))return true;
return false;
}
}
int bfs(){
memset(vis,0,sizeof(vis));
vis[0][0] = 1;
while(!q.empty()){q.pop();}
q.push(pi(0,0));
while(!q.empty()){
pi now = q.front();
q.pop();
if(now.first==n-1 && now.second==n-1) return step[now.first][now.second];
for(int i=0;i<8;i++){
int tx = now.first+dir[i][0];
int ty = now.second+dir[i][1];
if(tx<0 || tx>=n) continue;
if(ty<0 || ty>=n) continue;
if(vis[tx][ty]==1 || mapp[tx][ty]=='#') continue;
if(check({ty,tx},{now.second,now.first})) continue;
vis[tx][ty] = 1;
step[tx][ty] = step[now.first][now.second]+1;
q.push(pi(tx,ty));
}
}
return -1;
}
int main()
{
//cout<< onseg({0,0},{1,1},{0.999,0.999})<<endl;
while(~scanf("%d",&n)){
for(int i=0;i<3;i++){
double tx,ty;
scanf("%lf%lf",&tx,&ty);
trangle[i] = {tx,ty};
}
for(int i=n-1;i>=0;i--){
scanf("%s",mapp[i]);
}
int ans = bfs();
printf("%d\n",ans);
}
return 0;
}