码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-10-21 22:01:08      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:display   desc   cst   技术   eve   i++   2.0   div   can   

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);
    }
}
View Code

 

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

标签:display   desc   cst   技术   eve   i++   2.0   div   can   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!