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; }