ICPC 2017 北京 Liaoning Ship’s Voyage

来源:互联网 发布:ecshop小程序源码 编辑:程序博客网 时间:2024/04/28 23:41

题目地址:http://hihocoder.com/problemset/problem/1633?sid=1234017


题目大意:在二维平面内,船从(0,0)出发到(n-1,n-1)结束,求最短路,要求:一个点可以向周围8个方向走,距离都为1,并告诉哪些点不可以走,同时要求路线不可以穿过一个三角形。


题解:对每个点标号,建图,最后SPFA搞一下。连边时要判断路线是否穿过三角形,具体方法是,在路线上平均取100个点,若100个点都不在三角形中,则认为该路线没有穿过三角形。


#include<bits/stdc++.h>#define LL long longconst double eps=1e-7;using namespace std;int dcmp(double x){if (fabs(x)<eps)return 0;else return x<0?-1:1;}struct Point{    double x,y;    bool operator < (const Point &a)const    {return dcmp(x-a.x)<0 || (dcmp(x-a.x)==0 && dcmp(y-a.y)<0);}    Point(double x=0,double y=0):x(x),y(y){ }};typedef Point Vector;Vector operator + (Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}Vector operator - (Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}Vector operator * (Vector a,double b){return Vector(a.x*b,a.y*b);}Vector operator / (Vector a,double b){return Vector(a.x/b,a.y/b);}bool operator == (Vector a,Vector b){return a.x==b.x && a.y==b.y;}double Dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}  //点积double Length(Vector a){return sqrt(Dot(a,a));}double Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;} //叉积int i,j,k,l,n,m,t,h,en,d[410];Point a[4];int num[22][22];char x[22];int dx[8]={0,1,1,1,0,-1,-1,-1},dy[8]={1,1,0,-1,-1,-1,0,1};      //8个方向向量vector<int> G[410];bool isPointInPolygon(Point p)         //点在三角形内判定{    return dcmp(Cross(a[1]-a[0],p-a[0]))>0 && dcmp(Cross(a[2]-a[1],p-a[1]))>0 && dcmp(Cross(a[0]-a[2],p-a[2]))>0;}bool check(Point x,Point y)            //检查路线x->y是否穿过三角形{    for (int i=1;i<=1000;i++)    {        Point t=x+(y-x)/1000.0*(double)i;        if (isPointInPolygon(t)==1) return false;    }    return true;}int  SPFA(int n)                        //求最短路{    int i,j,k,l;    bool f[410]={0};    queue<int>q;    while (!q.empty())q.pop();    for (i=2;i<=n;i++) d[i]=1000000;    q.push(1);f[1]=1;d[1]=0;    while (!q.empty())    {        int x=q.front();q.pop();        for (int i=0;i<G[x].size();i++)        {            int v=G[x][i];            if (d[x]+1<d[v])            {                d[v]=d[x]+1;                if (!f[v])                {                    q.push(v);                    f[v]=1;                }            }        }        f[x]=0;    }    if (d[en]==1000000)return -1;else return d[en];}int main(){    while (~scanf("%d",&n))    {        memset(num,0,sizeof num);memset(G,0,sizeof G);        for (i=0;i<3;i++) scanf("%lf%lf",&a[i].x,&a[i].y);        if (dcmp(Cross(a[1]-a[0],a[2]-a[0]))<0) swap(a[1],a[2]);        for (i=n-1;i>=0;i--)        {            scanf("%s",x);            for (j=0;j<n;j++)if (x[j]=='#' || isPointInPolygon(Point(j,i))==1) num[i][j]=-1;        }        t=0;        for (i=0;i<n;i++)for (j=0;j<n;j++) if (num[i][j]!=-1)num[i][j]=++t;     //标号                for (i=0;i<n;i++)            for (j=0;j<n;j++) if (num[i][j]!=-1)                                //建图        {            for (k=0;k<8;k++)            {                int x=i+dx[k],y=j+dy[k];                if (!(x>=0 && x<n && y>=0 && y<n && num[x][y]!=-1))continue;                if (check(Point(j,i),Point(y,x)))                {                    int u=num[i][j],v=num[x][y];                    G[u].push_back(v);                }            }        }                en=num[n-1][n-1];        if (en==-1)printf("-1\n");else printf("%d\n",SPFA(en));    }    return 0;}