ACM-ICPC Beijing Division 2017 Network Synchronized Competition G

http://hihocoder.com/contest/icpcbeijing2017/problem/7

bfs + computational geometry

The difficulty is the relationship between the line segment and the triangle. There are three cases: 1. The endpoints of the line segment 2 are all outside the triangle. Determine whether the line segment and the three sides of the triangle intersect in a standard way. 2. One endpoint of the line segment is inside or on the triangle, and the other is outside the triangle. A point is a little bit closer, and then judge whether it is inside the triangle 3. Both points are inside or above the triangle, see if the midpoint is inside the triangle

Computational geometry is a dish

#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pi;
const int maxn = 29;
char folder [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 {xa.x,ya.y};
    }
    Point operator +(const Point&a){
        return {x+ax,y+ay};
    }
    double operator *(const Point&a){
        return x*a.x+y*ay;
    }
    Point operator *(const double  &a){
        return {x*a,y*a};
    }
    double operator ^(const Point&a){
        return x*ay-y*ax;
    }

};
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;
}
Trangle Point [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;
}
intmain()
{
    //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;
}

  

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324634001&siteId=291194637