房间最短路问题

https://www.luogu.org/problemnew/show/P1354

直接做,一个缺口上的两个边界分别看成两个点,这样我们就有n * 4个点

然后对于一堵墙,我们尝试将其与后面的点连边

有可能有连不上的情况,就是这条路线撞墙上了,算出一次函数的解析式判断一下即可

然后愉快跑floyd,反正这题n^3和n^2都能过

O(n ^ 3)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath> 
#include<iostream>
using namespace std;
#define O(x) cout << #x << " " << x << endl;
#define B cout << "breakpoint" << endl;
inline int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') op = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        (ans *= 10) += ch - '0';
        ch  = getchar();
    }
    return ans * op;
}
typedef double db;
const db inf = 99999999;
const int maxn = 1005;
int n;
db dis[maxn][maxn];
void init()
{
    for(int i = 1;i <= 4 * n + 4;i++) 
        for(int j = 1;j <= 4 * n + 4;j++)
            dis[i][j] = inf;
    for(int i = 1;i <= n * 4 + 4;i++) dis[i][i] = 0;
}
void floyd()
{
    for(int k = 1;k <= n * 4 + 4;k++)
        for(int i = 1;i <= n * 4 + 4;i++)
            for(int j = 1;j <= n * 4 + 4;j++)
                dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);
}

struct node
{
    db x,y[5];
}a[maxn];
bool judge(int u,int v,int t1,int t2)//a的第t1个节点,b的第t2个节点 
{
    if(v - u == 1) return 1;
    db x1 = a[u].x,x2 = a[v].x,y1 = a[u].y[t1],y2 = a[v].y[t2];
    db k = (y2 - y1) / (x2 - x1);
    db b = y1 - k * x1;
    for(int i = u + 1;i <= v - 1;i++)
    {
        db y = k * a[i].x + b;
        if(y < a[i].y[1] || y > a[i].y[2] && y < a[i].y[3] || y > a[i].y[4]) return 0;
    }
    return 1;
}
void link_edge(int u,int v,int t1,int t2)
{
    if(judge(u,v,t1,t2) == 0) return;
    db x1 = a[u].x,x2 = a[v].x,y1 = a[u].y[t1],y2 = a[v].y[t2];
    db d = sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1));
    dis[u * 4 + t1][v * 4 + t2] = dis[v * 4 + t2][u * 4 + t1] = d;
}
int main()
{
    n = read();
    for(int i = 1;i <= n;i++)
        scanf("%lf%lf%lf%lf%lf",&a[i].x,&a[i].y[1],&a[i].y[2],&a[i].y[3],&a[i].y[4]);
    a[0].x = 0,a[++n].x = 10;
    init();
    for(int i = 1;i <= 4;i++) a[0].y[i] = a[n].y[i] = 5;
    for(int i = 0;i <= n;i++)
        for(int j = i + 1;j <= n;j++)
            for(int k = 1;k <= 4;k++)
                for(int p = 1;p <= 4;p++)
                    link_edge(i,j,k,p);
    floyd();
    printf("%.2lf",dis[1][n * 4 + 4]);
}
            
View Code

 

posted on 2019-04-16 20:20  L_M_A  阅读(593)  评论(0编辑  收藏  举报

导航