Maze Stretching Poj3897 二分+BFS

Description

Usually the path in a maze is calculated as the sum of steps taken from the starting point until the ending point, assuming that the distance of one step is exactly 1. Lets assume that we could “stretch” (shorten or extend) the maze in vertical dimension (north-south). By stretching, we are just changing the passed distance between two cells. (it becomes X instead of one). We have a two dimensional maze which has ‘#‘ for walls, ‘S‘ in the starting cell and ‘E‘ at the ending cell.
Due to outside conditions, we need to make the shortest path
to be exactly L in size. We are not allowed to change the maze
configuration, nor to make any changes in the horizontal dimension. We
are only allowed to stretch the vertical dimension, and that can be done
by any percentage.

Find the percentage of the stretch P, for which the shortest path of the maze will be exactly L.

Input

First line of the input contains the number of test cases. For each
test case, firstly two numbers L and N are given, where L is the
required length of the shortest path and N is the number of lines that
are given describing the maze. The following N lines describes the maze
such as that each line describes a row of the maze. (Each row length is
the horizontal dimension of the maze).

Output

For each test case output the percentage of the stretch in the following format:

Case #K: P%

- P should have leading zero if the number is between 0 and 1.

- P should be rounded up on 3 decimals, and always formatted on 3 decimals (with trailing zeros if needed).

Sample Input

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

Sample Output

Case #1: 50.000%
Case #2: 21.053%

Hint

Constraints
The height and width of the maze are maximum 100 cells.

All the lines describing one maze are the same size.

There will always be a solution.

The result will be between 0.000 and 1000.000 inclusive
There will be no direct horizontal only path connecting ‘S‘ and ‘E‘. (the result is always unique).

Explanation of the first test case in the example:
On the original maze, the length of the shortest path is 3 because
there are two horizontal steps and a vertical one. Our goal is to make
the length of the shortest path to be 2.5. That’s why we have to
“stretch” the vertical dimension of the maze by a percentage value less
than 100. In this case it is 50% which actually changes the vertical
distance between two cells to 0.5.

题意:给出一张标记了起点和终点的图,对纵轴进行伸缩变换使从起点到终点的最短路等于给定值。

分析:

  二分伸缩的可能情况,对于每种伸缩都有对应不同的最短路,那么对路程总值val经行标记,记录下BFS中到达每一点的最短路程,最后返回终点的最短路程,继续二分。

  一开始简单的认为最短路一定是固定的 ,其实不然,看张图

#######

#  S       #

#  ###   #

#  #E     #

#  #   ###

#       ###

#######

此时当纵向伸缩足够小时,就变成了从左边走为最短路。

然后继续简单的认为用优先队列记录step就能解决问题。。。。。。

其实不然,看张图。。。。。。

###  ###

###  ###

E

###  ###

###  ###

当从四个方向接近E时可能发生这种情况:横向与竖向同时距离终点一格而竖向或横向的到终点step更小;当然,也有可能还有其它图有各种方案到达E并且step更小(脑补)。

*所以这里要想不管这么多就直接暴搜全图并记录最短路径值吧。

Q:为什么想到二分?

A:感觉。。。。。。

仔细想想这题 还是蛮有意思的

  1 #include<cstring>
  2 #include<cstdio>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<queue>
  6
  7 #define eps 1e-9
  8 #define INF 0x3f3f3f3f
  9 using namespace std;
 10
 11 struct node
 12 {
 13     int x,y;
 14     double step;
 15     friend bool operator < (node A,node B)
 16     {
 17         return A.step>B.step;
 18     }
 19 };
 20
 21 priority_queue<node>que;
 22
 23 char g[105][105];
 24 int vis[105][105];
 25 double val[105][105];//存储每次BFS的最短路径值
 26 int dir[][5]={{-1,0},{1,0},{0,-1},{0,1}};
 27 int x,y,xx,yy;
 28 int n,m;
 29 double aim;
 30
 31
 32 bool judge(int a,int b)
 33 {
 34     if(a>=0&&a<n&&b>=0&&b<m) return true;
 35     return false;
 36 }
 37
 38 double bfs(double mid)
 39 {
 40     while(que.size()) que.pop();
 41     memset(vis,0,sizeof vis);
 42
 43     for(int i=0;i<n;i++)
 44         for(int j=0;j<m;j++)
 45         val[i][j]=INF;
 46
 47     node k;
 48     k.x=x;
 49     k.y=y;
 50     k.step=0;
 51     que.push(k);
 52
 53     while(que.size())
 54     {
 55         k=que.top();
 56         que.pop();
 57
 58         for(int i=0;i<4;i++)
 59         {
 60             node temp=k;
 61             temp.x+=dir[i][0];
 62             temp.y+=dir[i][1];
 63             if(judge(temp.x,temp.y)&&g[temp.x][temp.y]!=‘#‘)
 64             {
 65                 vis[temp.x][temp.y]=1;
 66                 double T_T;
 67                 if(i==0||i==1) T_T=mid;
 68                 else T_T=1;
 69                 temp.step+=T_T;//= =、
 70
 71                 if(!vis[temp.x][temp.y]||(vis[temp.x][temp.y]&&temp.step<val[temp.x][temp.y]))//未访问过或者访问过但此时值更小,记录。
 72                 {
 73                     vis[temp.x][temp.y]=1;
 74                     val[temp.x][temp.y]=temp.step;
 75                     que.push(temp);
 76                 }
 77
 78             }
 79         }
 80     }
 81     return val[xx][yy];
 82 }
 83
 84 int main()
 85 {
 86     int T;
 87     double ans;
 88     scanf("%d",&T);
 89     for(int k=1;k<=T;k++)
 90     {
 91         scanf("%lf%d",&aim,&n);
 92         getchar();
 93         for(int i=0;i<n;i++)
 94             gets(g[i]);
 95
 96         m=strlen(g[0]);
 97
 98         for(int i=0;i<n;i++)
 99             for(int j=0;j<m;j++)
100             if(g[i][j]==‘S‘)
101             {
102                 x=i;
103                 y=j;
104             }
105             else if(g[i][j]==‘E‘)
106             {
107                 xx=i;
108                 yy=j;
109             }
110
111
112         double r=0,l=1000000;
113         while(r+eps<l)
114         {
115             double mid=(r+l)/2;
116             if(bfs(mid/100)>aim) l=mid;
117             else r=mid;
118         }
119         ans=r;
120         printf("Case #%d: %.3lf%%\n",k,ans);
121     }
122 }
时间: 2024-11-03 23:12:35

Maze Stretching Poj3897 二分+BFS的相关文章

hdu 4400 离散化+二分+BFS(暴搜剪枝还超时的时候可以借鉴一下)

Mines Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1110    Accepted Submission(s): 280 Problem Description Terrorists put some mines in a crowded square recently. The police evacuate all peo

CUGBACM_Summer_Tranning3 2013长沙现场赛(二分+bfs模拟+DP+几何)

A题:二分 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4791 用lower_bound可以轻松解决,不过比赛的时候逗逼了. 刚开始没有预处理,所以队友给出一组数据的时候没通过,然后一时紧张又想不出什么好的解决办法,所以就没再继续敲代码.实在有点可惜了. #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #includ

{POJ}{3897}{Maze Stretching}{二分答案+BFS}

题意:给定迷宫,可以更改高度比,问如何使最短路等于输入数据. 思路:由于是单调的,可以用二分答案,然后BFS验证.这里用优先队列,每次压入也要进行检查(dis大小)防止数据过多,A*也可以.好久不写图论,WA成狗 #include <iostream> #include <string> #include <cstring> #include <cstdio> #include <algorithm> #include <memory>

hiho_1139_二分+bfs搜索

题目 给定N个点和M条边,从点1出发,寻找路径上边的个数小于等于K的路径,求出所有满足条件的路径的路径中最长边长度的最小值. 题目链接:二分     最小化最大值,考虑采用二分搜索.对所有的边长进行排序,二分,对每次选择的边长,判断是否存在一条路径满足路径上所有的边长度均小于等于该边长,且路径中的边的个数小于等于K.     在判断路径是否存在的时候,使用BFS搜索,因为BFS用于寻找最短(边的个数最少)路径. 实现 #include<stdio.h> #include<string.h

WHYZOJ-#95 大逃亡(二分+BFS)(好题!!!)

[题目描述]: 给出数字N,X,Y,代表有N个敌人分布一个X行Y列的矩阵上,矩形的行号从0到X-1,列号从0到Y-1再给出四个数字x1,y1,x2,y2,代表你要从点(x1,y1)移到(x2,y2).在移动的过程中你当然希望离敌人的距离的最小值最大化,现在请求出这个值最大可以为多少,以及在这个前提下,你最少要走多少步才可以回到目标点.注意这里距离的定义为两点的曼哈顿距离,即某两个点的坐标分为(a,b),(c,d),那么它们的距离为|a-c|+|b-d|. [输入描述]: 第一行给出数字N,X,Y

BZOJ 1514 _ [POI2006]ZAB-Frogs 单调队列+二分BFS

题意: 给定一个网格图,其中有一些坏点,要求使起点到终点的路径上的所有点到离该点最近的坏点的最小距离距离最大,求这个最大值. 解析: 读完题显然分为两部分: 第一部分:预处理所有点到他最近的坏点的距离. 第二部分:二分最大距离bfs判定. 第二部分不用说吧? 主要就是卡在第一部分. 我们考虑按照每列来计算每个点的dis距离(即到他最近的坏点的距离) 显然可以发现,对于该列来说,每一行都可能有一个到该列最近的点,并且我们发现,如果某一行有两个坏点的话,假设分别为A,B,并且A到该列的距离最近,那么

zoj 3820 Building Fire Stations(二分+bfs)

题目链接:zoj 3820 Building Fire Stations 题目大意:给定一棵树,选取两个建立加油站,问说所有点距离加油站距离的最大值的最小值是多少,并且任意输出一种建立加油站的方式. 解题思路:二分距离判断,判断函数的复杂度是o(n),这样的复杂度应该是o(nlogn),即使常数系数偏大,但是居然跑了4.5s,也是醉了. 判断函数里面做了3次bfs,但是每次bfs节点最多遍历1次,首先任取一点做根建立一个树,找到深度最大的节点,以向上移动L(判断的ans)位置处的节点建立加油站,

POJ 2110 Mountain Walking 二分+bfs

传送门 昨天看到这个题还以为是个脑残的dp, 然而脑残的是我. 题目意思就是从左上角走到右下角, 设x为路径上的最大值-最小值, 求x的最小值. 二分x, 对于每一个x, 枚举下界lower, lower从0开始枚举, 每一次bfs的时候, 如果一个点的值小于lower或者大于lower+x, 那么就不走这个点, 看最后能否走到终点. 自己的整数二分写的真是不忍直视...改了好久. 1 #include<bits/stdc++.h> 2 using namespace std; 3 #defi

poj 3501 Escape from Enemy Territory 预处理+二分+bfs

传送门 给一个起点一个终点, 给出整个地图的宽和高, 给出n个敌人的坐标. 让你找到一条路径, 这条路径上的点距离所有敌人的距离都最短, 输出最短距离. 首先预处理出来地图上的所有点到敌人的最短距离, 然后二分距离, bfs就可以. tle了好多次, 到网上搜题解, 看到别人是先把敌人的坐标都存到数组里最后在一起预处理, 而我是读一个点处理一个点, 改了以后才ac....... 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define