zoukankan      html  css  js  c++  java
  • [Luogu P1354]房间最短路问题

    这是一道紫题,然而实际上我觉得也就蓝题难度甚至不到。

    and,这道题就是一道数学题,代码模拟计算过程。

    求最短路嘛,肯定要考虑建图,只需要把中间的墙上每个口的边缘处的点作为图中的点就行。至于为什么,显然如果我们取中间任何一个点连边,到下一面墙时路径之和总是比连其中一个边缘的点要大,直观感(gán觉(juě)一下就行。连边我们一定会遇到一个问题,就是会被墙挡住。解决办法就是一次函数。我们求出要连这条边的直线解析式(直接模拟计算过程就行),然后求出在中间的墙上的函数值,如果这个函数值正好在缺口处就可以,否则被墙挡住,中间有多面墙枚举就行。

    当我们建完图后这题就是最短路板子题了。n<=20,直接Floyd就水过去了。

    据说lbg直接用dfs暴力水过去了,tql!

    参考代码:

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define N 100
    using namespace std;
    int s;
    double dis[N][N];
    struct wall
    {
        double x;
        double y[5];
    }w[30];
    bool check(int a,int b,int na,int nb)
    {
        if(b - a <= 1) return 1;
        double ya = w[a].y[na],yb = w[b].y[nb],xa = w[a].x,xb = w[b].x;
        double k = (ya - yb) / (xa - xb);
        double bb = ya - k * xa;//模拟待定系数法
        for(int i = a + 1;i < b;i++)
        {
            double y = w[i].x * k + bb;
            if(y < w[i].y[1] || (y > w[i].y[2] && y < w[i].y[3]) || y > w[i].y[4]) return 0;//判断是否被墙挡住
        }
        return 1;
    }
    void add(int a,int b,int na,int nb)
    {
        if(!check(a,b,na,nb)) return;
        dis[4 * a + na][4 * b + nb] = dis[4 * b + nb][4 * a + na] = sqrt((w[a].x - w[b].x) * (w[a].x - w[b].x) + (w[a].y[na] - w[b].y[nb]) * (w[a].y[na] - w[b].y[nb]));//连边,边权为两点间距离
    }
    void reset()
    {
        for(int i = 0;i <= N;i++)
        {
            for(int j = 0;j <= N;j++)
            {
                if(i != j) dis[i][j] = 1e8;
                else dis[i][j] = 0;
            }
        }
    }
    void floyd()
    {
        for(int k = 1;k <= 4 * s + 4;k++)
        {
            for(int i = 1;i <= 4 * s + 4;i++)
            {
                for(int j = 1;j <= 4 * s + 4;j++)
                {
                    dis[j][i] = dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);
                }
            }
        }
        return;
    }
    int main()
    {
        reset();
        scanf("%d",&s);
        for(int i = 1;i <= s;i++)
        {
            scanf("%lf %lf %lf %lf %lf",&w[i].x,&w[i].y[1],&w[i].y[2],&w[i].y[3],&w[i].y[4]);
        }
        w[0].x = 0;w[++s].x = 10;
        for(int i = 1;i <= 4;i++) w[0].y[i] = w[s].y[i] = 5;
        for(int a = 0;a < s;a++)
        {
            for(int b = a + 1;b <= s;b++)
            {
                for(int na = 1;na <= 4;na++)
                {
                    for(int nb = 1;nb <= 4;nb++)
                    {
                        if(a == b) continue;
                        add(a,b,na,nb);
                    }
                }
            }
        }
        floyd();
        printf("%.2lf",dis[1][4 * s + 1]);
        
    }
  • 相关阅读:
    nodejs REPL清屏
    flask 的relationship使用
    flask 数据库多对多(文章和标签)
    设置管理员的 蘑菇丁日报 周报、月报
    访问个人主页、蘑菇丁、使用:import urllib.request
    使用requests访问、登录蘑菇丁
    UUID
    爬虫经典案例
    selenium 获取 cookies, 然后登录
    用chrome浏览器登录以后 手动找到cookie、加到自己的python代码中
  • 原文地址:https://www.cnblogs.com/lijilai-oi/p/10720386.html
Copyright © 2011-2022 走看看