2017北京区域赛 G - Liaoning Ship’s Voyage【计算几何+bfs】

题目大意:一个图上有n*n个点,然后从起点走到终点,然后需要绕过三角形和“#”,问一个最短路径
分析:由于边上的点和端点都是能走的,我在扩展边的时候,判断该边与三角形是否有焦点,我原先是判断线段与线段的交点,然后判断点是否在三角形内部,后来发现如果一个线段的起点和终点都不在三角形内部的话,也是有可能穿过三角形的,所以后来我们枚举了线段上的100个点,判断是否在三角形内部

#include <bits/stdc++.h>
using namespace std;
char mp[50][50];
int dist[50][50];
const int inf=0x3f3f3f3f;
double eps=1e-8;
int n;
struct point
{
    double x,y;
    point(double X=0,double Y=0)
    {
        x=X,y=Y;
    }
};
point operator +(point a,point b)
{
    return point(a.x+b.x,a.y+b.y);
}
point operator -(point a,point b)
{
    return point(a.x-b.x,a.y-b.y);
}
point operator *(point a,double p)
{
    return point(a.x*p,a.y*p);
}
point operator /(point a,double p)
{
    return point(a.x/p,a.y/p);
}
double len(point a)
{
    return sqrt(a.x*a.x+a.y*a.y);
}
double dot(point a,point b)
{
    return a.x*b.x+a.y*b.y;
}
double cross(point a,point b)
{
    return a.x*b.y-a.y*b.x;
}
int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    else return x<0?-1:1;
}
bool operator == (point a,point b)
{
    if(dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0)return true;
    else return false;
}
bool segment(point a,point b,point c,point d)
{
    double c1 = cross(b-a,c-a);
    double c2 = cross(b-a,d-a);
    double d1 = cross(d-c,a-c);
    double d2 = cross(d-c,b-c);
    return dcmp(c1)*dcmp(c2)<0&&dcmp(d1)*dcmp(d2)<0;
}
double dists(point p,point a,point b)
{
    if(a==b) return len(p-a);
    point v1 = b-a,v2 = p-a,v3=p-b;
    if(dcmp(dot(v1,v2))<0) return len(v2);
    else if(dcmp(dot(v1,v3))>0) return len(v3);
    return fabs(cross(v1,v2))/len(v1);
}
point tri[5];
int pointin(point p,point *a,int n)
{
    int wn = 0,k,d1,d2;
    for(int i=1; i<=n; i++)
    {
        if(dcmp(dists(p,a[i],a[i%n+1]))==0) return 0;
        k = dcmp(cross(a[i%n+1]-a[i],p-a[i]));
        d1 = dcmp(a[i].y-p.y);
        d2 = dcmp(a[i%n+1].y-p.y);
        if(k>0&&d1<=0&&d2>0) wn++;
        if(k<0&&d2<=0&&d1>0) wn--;
    }
    if(wn) return 1;
    else return 0;
}
bool check(int x,int y,int fx,int fy)
{
    if(fx<0||fx>=n||fy<0||fy>=n)return false;
    if(mp[x][y]=='#'||mp[fx][fy]=='#')return false;
    point a,b,c;
    a.x=y;
    a.y=x;
    b.x=fy;
    b.y=fx;
    for(int i=1; i<=3; i++)
    {
        if(segment(a,b,tri[i],tri[i%3+1])) return false;
    }
    if(pointin(a,tri,3)) return false;
    if(pointin(b,tri,3)) return false;
    for(int i=1;i<=100;i++)
    {
        double p = i*0.01;
        c.x=a.x+(b.x-a.x)*p;
        c.y = a.y+(b.y-a.y)*p;
        if(pointin(c,tri,3)) return false;
    }
    return true;
}
int fx[8] = {0, 0, 1,-1, 1, 1,-1,-1};
int fy[8] = {1,-1, 0, 0, 1,-1, 1,-1};
int d[500];
bool bfs(int s, int t)
{
    memset(d,-1,sizeof(d));
    queue<int> q;
    q.push(s*n+t);
    d[s*n+t]=0;
    while(!q.empty())
    {
        int u  = q.front();
        q.pop();
        int x = u/n;
        int y = u%n;
        if(u == n*n-1)  return true;
        for(int i = 0; i < 8; i++)
        {
            int fx1 = x + fx[i];
            int fy1 = y + fy[i];
            if(check(x,y,fx1,fy1) && d[fx1*n+fy1] == -1)
            {
                d[fx1*n+fy1] = d[u] + 1;
                q.push(fx1*n+fy1);
            }
        }
    }
    return false;
}


int main()
{

    while(~scanf("%d",&n))
    {
        for(int i=1; i<=3; i++)
        {
            scanf("%lf%lf",&tri[i].x,&tri[i].y);
        }
        /*point st=point(1.5,1);
        cout<<pointin(st,tri,3)<<endl;*/
        for(int i=n-1; i>=0; i--)
        {
            scanf("%s",mp[i]);
        }
        if(bfs(0,0))
        {
            printf("%d\n",d[n*n-1]);
        }
        else printf("-1\n");
    }
    return 0;
}
/*
4
1 1 2 2 0 2
#...
#.##
#.##
..##


*/
全部评论

相关推荐

10-15 18:02
已编辑
香港中文大学 golang
秋招有幸一开始就拿了淘天的笔面,并且美团转正的意向也顺利通过后续在淘天和字节两个&nbsp;9&nbsp;月主要流程都走到了&nbsp;hr&nbsp;面,国庆节后一个通过,一个横向挂了其他面过的包括:b&nbsp;站一面挂&nbsp;八股还行,最后手撕给了个笔试压轴限时&nbsp;15min...整段垮掉阿里控股&nbsp;kpi一面➕换部门走到二面,控股的都不喜欢开摄像头京东一面挂&nbsp;常规问题,但是疑似成都&nbsp;base&nbsp;hc&nbsp;很少,并且透露了已经转正,目前池子里无人捞腾讯正在二面&nbsp;一面体验不错,还指出了要改进的地方,提示二面不会再问问过的问题快手一面未知小红书一面未知字节换部门一面不喜欢业务,又回到了人才库大麦约面,准备拒掉虾皮一面&nbsp;无后续流程,面试聊的还行,感觉上海&nbsp;base&nbsp;池子满了---------------------------------------------------------------------------感觉秋招可以结束了,后续感觉走完这个腾讯流程就随缘面面&nbsp;t&nbsp;和&nbsp;b,主包家在南京,奈何南京没啥好的民营企业和互联网氛围,以及好国企又太难进,不知道淘天这个意向够不够直接结束秋招了...今天去深圳&nbsp;nip&nbsp;主场看了一下入围赛,主队不是这两家,还是觉得&nbsp;ig&nbsp;可惜了,有很好的机会没有抓住。感触和我字节&nbsp;hr&nbsp;面挂一样评论区有推荐的字节杭州上海base的业务线或者有字节&nbsp;hr&nbsp;uu&nbsp;可以捞一下吗?
肖先生~:大佬都这么强了还要干啥啊
我的求职进度条
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务