[二分][记搜]JZOJ 3522 迷宫花园

Description

给定一个一定存在从起点到终点的路径的四联通迷宫。已知Tar左右方向移动的时间为1,上下移动的时间为未知实数v。求当Tar从起点到终点的最短移动时间为已知实数L时,未知实数v是多少。

Input

输入数据包含多个测试点。第一行为一个整数T,表示测试点的数目。

对于每一个测试点,第一行包含实数L和两个整数R,C。R为迷宫的上下长度,C为迷宫的左右长度。

之后的R行,每行包含C个字符。其中空格表示空地,S表示起点,E表示终点,#表示围墙。

Output

对于每一个测试点,在单独的一行内输出未知实数v,输出保留5位小数。

Sample Input

2                                 
2.5 4 5                           
#####
#S  #
#  E#
#####
21 13 12
############
#S##     #E#
# ##  #  # #
#   # #  # #
### # #  # #
#   # #  # #
#  ## #  # #
##  # #  # #
### # #  # #
##  # #  # #
#  ## #    #
#     #    #
############

Sample Output

0.50000
0.21053

Data Constraint

20%的数据,1≤ R,C ≤ 10。

100%的数据,1≤ R,C ≤ 100,0≤ v <10。

分析

二分+记忆化搜索,注意BFS中已在队列中的不要反复加入,会T

#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;
const int N=110;
struct Point {
    int x,y;
}s,e;
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
double f[N][N];
char ch[N][N];
int t,r,c;
double l,v;
bool inqueue[N][N];

double Cost(Point a,Point b) {
    if (abs(a.y-b.y)==1) return 1.0;
    else return v;
}

bool Judge(Point a,Point b) {
    if (b.x<1||b.x>r||b.y<1||b.y>c) return 0;
    if (ch[b.x][b.y]==‘#‘) return 0;
    if (f[a.x][a.y]+Cost(a,b)>f[b.x][b.y]) return 0;
    return 1;
}

void Bfs()  {
    queue<Point> q;
    while (!q.empty()) q.pop();
    for (int i=1;i<=r;i++)
        for (int j=1;j<=c;j++)
            f[i][j]=2147483647.0;
    q.push(s);f[s.x][s.y]=0;inqueue[s.x][s.y]=1;
    while (!q.empty()) {
        Point p=q.front();q.pop();
        for (int i=0;i<4;i++)
            if (Judge(p,(Point){p.x+dx[i],p.y+dy[i]})) {
                Point to=(Point){p.x+dx[i],p.y+dy[i]};
                f[to.x][to.y]=f[p.x][p.y]+Cost(p,to);
                if (!inqueue[to.x][to.y]) q.push(to);
                inqueue[to.x][to.y]=1;
            }
        inqueue[p.x][p.y]=0;
    }
}

int main() {
    freopen("maze.in","r",stdin);
    freopen("maze.out","w",stdout);
    scanf("%d",&t);
    for (;t;t--) {
        scanf("%lf%d%d",&l,&r,&c);
        for (int i=1;i<=r;i++)
            for (int j=1;j<=c;j++) {
                do {
                    scanf("%c",&ch[i][j]);
                }
                while (ch[i][j]!=‘#‘&&ch[i][j]!=‘E‘&&ch[i][j]!=‘S‘&&ch[i][j]!=‘ ‘);
                if (ch[i][j]==‘E‘) e.x=i,e.y=j;
                if (ch[i][j]==‘S‘) s.x=i,s.y=j;
            }
        double ll=1e-7,rr=10.0;
        while (rr-ll>=1e-7) {
            v=(ll+rr)/2.0;
            Bfs();
            if (f[e.x][e.y]<l) ll=v+1e-7;
            else rr=v;
        }
        printf("%.5lf\n",v);
    }
}

原文地址:https://www.cnblogs.com/mastervan/p/9826700.html

时间: 2024-10-06 22:25:18

[二分][记搜]JZOJ 3522 迷宫花园的相关文章

[bfs] Jzoj P3522 迷宫花园

Description 给定一个一定存在从起点到终点的路径的四联通迷宫.已知Tar左右方向移动的时间为1,上下移动的时间为未知实数v.求当Tar从起点到终点的最短移动时间为已知实数L时,未知实数v是多少. Input 输入数据包含多个测试点.第一行为一个整数T,表示测试点的数目. 对于每一个测试点,第一行包含实数L和两个整数R,C.R为迷宫的上下长度,C为迷宫的左右长度. 之后的R行,每行包含C个字符.其中空格表示空地,S表示起点,E表示终点,#表示围墙. Output 对于每一个测试点,在单独

二分+最短路判定 BZOJ 2709: [Violet 1]迷宫花园

BZOJ 2709: [Violet 1]迷宫花园 Sample Input 5 10.28 9 9 ######### # # # # # # # #S# # ##### # # ## # # # ### ### ##E # ######### 4.67 9 9 ######### # ## ## ### #S# # # # E ## # # ##### # ## ### # ##### # # # # ######### 39.06 9 9 ######### # # # # # # # #

【二分答案】【Heap-Dijkstra】bzoj2709 [Violet 1]迷宫花园

显然最短路长度随着v的变化是单调的,于是可以二分答案,据说spfa在网格图上表现较差. #include<cstdio> #include<cstring> #include<queue> using namespace std; typedef double db; typedef long long ll; #define N 101 #define INF 2147483647.0 #define EPS 0.0000001 struct Point{db d;i

宽搜-走出迷宫

描述 当你站在一个迷宫里的时候,往往会被错综复杂的道路弄得失去方向感,如果你能得到迷宫地图,事情就会变得非常简单. 假设你已经得到了一个n*m的迷宫的图纸,请你找出从起点到出口的最短路. 输入第一行是两个整数n和m(1<=n,m<=100),表示迷宫的行数和列数.接下来n行,每行一个长为m的字符串,表示整个迷宫的布局.字符'.'表示空地,'#'表示墙,'S'表示起点,'T'表示出口.输出输出从起点到出口最少需要走的步数.样例输入 3 3 S#T .#. ... 样例输出 6 普通的搜索,但数据

【BZOJ1052】【HAOI2007】覆盖问题 二分+深搜check

题解:乱搞. 就是搜每个正方形的位置(一定在一个角,证明自己想想吧,很容易但是不算太好写) 代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 20100 #define inf 0x3f3f3f3f using namespace std; struct Point { int x,y; Point(int _x=0,int

HDU 1026 Ignatius and the Princess I 迷宫广搜剪枝问题

本题是个经典的迷宫广搜问题类型了.网上看到好多解法. 很多解题报告都没什么分析,更不会指出其中的关键点.代码更加像一大抄.有人分析也一大篇分析,不过全部都不切中关键,甚至在分析什么广搜和深搜区别,广搜为什么快之类的,还有喊什么暴搜之类的,全错了.估计这些代码都是抄过的. 通过一大段的时间研究,终于搞通了. 本题虽然可以说是广搜,但是其中的关键却是剪枝法,为什么呢? 因为迷宫并不能简单地广搜就能搜索出所有路径的,甚至只要迷宫大点就不能搜索出是否有路径,如果没有条件剪枝的情况下:不信,你严格写一个广

求迷宫多条最短路径

#include <iostream> #include <string> #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <stack> using namespace std; const int SIZE = 102; //边界数组,四个方向,按照下.右.上.左的顺序 int coordinate[4]

二分题目总结

在UVA上搜索二分时搜到了一个很好的public专题 1.POJ - 3258 River Hopscotch http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=16277 解题思路:http://blog.csdn.net/l123012013048/article/details/45646911 这题是符合条件的情况下,解有可能是偏小的 2.POJ - 3273 Monthly Expense http://acm.hu

1605 迷宫

难度:普及- 题目类型:深搜 提交次数:1 涉及知识:深搜 题目背景 迷宫 [问题描述] 给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过.给定起点坐标和 终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案.在迷宫 中移动有上下左右四种方式,每次只能移动一个方格.数据保证起点上没有障碍. 输入样例 输出样例 [数据规模] 1≤N,M≤5 题目描述 输入输出格式 输入格式: [输入] 第一行N.M和T,N为行,M为列,T为障碍总数.第二行起点坐标SX,SY,终点 坐