JZOJ3522. 迷宫花园(maze)

作为一名孱弱,刷了JZ的题,发现自己是如何的弱~~~~~~~

题目描述

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

Input

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

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

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

Output

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

样例

输入

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

输出

0.50000
0.21053

Data Constraint

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

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


本人感受:

这道题做完交后只有90分,孱弱的我找了半个小时没发现哪里出错,只能先去吃饭,下午回来拿到数据检查了一下,(嗯嗯~~~又掉进坑里了~~~~~)这是个巨坑,不过数据还是挺给力的,三个坑都在同一个点,所以才90分,不然,呵呵呵呵呵呵呵呵呵呵呵。

解析:

别人都是二分+bfs,而我是直接上bfs,时间8ms+空间468KB。

从起点开始扫,开个数据结构struct node{int y,x,cnty,cntx},分别记录坐标和向上下、左右走的步数(用于计算答案)。

根据题意得出:1*t.cntx+ans*t.cnty = l;     所以ans = (double)(l-t.cntx)/t.cnty;

注意:1、题目数据提到答案是0<=v<10,所以需要判定if(ans>=0),(被这个坑了一个点),<0就把终点a[ey][ex]标记为0且退出这层循环(不退出会导致循环继续从终点走向剩下的路,剩下的路中就包含正确的路,将会得不到答案)。

2、这是一个小tips,注意二维数据的哪一维对应y,x,(身边的大神开始也犯了这个问题。。)建议a[y][x],注意我的q.push((node){yy,xx,cnty,cntx})与定义时一一对应,不然有bug。

最后附上愚人的代码(羸弱)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#define re register int
using namespace std;
const int maxn = 105;
int a[maxn][maxn],t,n,m,sx,sy,ex,ey;
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};
double l,ans;
char c;
struct node{
	int y,x,cnty,cntx;
};
inline char readc(){                    //快速读入
	char ch = getchar();
	while(!(ch=='#'||ch=='S'||ch=='E'||ch==' ')) ch =getchar();
	return ch;
}
double bfs(){
	queue<node> q;
	q.push((node){sy,sx,0,0});
	a[sy][sx] = 1;
	node t;
	re yy,xx;
	while(!q.empty()){
		t = q.front();
		q.pop();
		if(t.y == ey&&t.x ==ex){        //比较喜欢先压入队列,取出来在判断终点
			ans = (double)(l-t.cntx)/t.cnty;
			if(ans>=0){
				return ans;
			}else{
				a[t.y][t.x] = 0;//****防止首先扫到的解不是正数,并且它会 
				continue;		//从终点扫向另一条路(正解)导致另一条路 
			}					//的解无法得到 
		}
		for(re i=0; i<=3; i++){	
			yy = t.y+dy[i];
			xx = t.x+dx[i];
			if(xx<1||yy<1||xx>m||yy>n||a[yy][xx]) continue;
			a[yy][xx] = 1;
			if(dx[i]!=0) q.push((node){yy,xx,t.cnty,t.cntx+1});
			if(dy[i]!=0) q.push((node){yy,xx,t.cnty+1,t.cntx});  
		}
	}
	return 0;
}
int main(){
	freopen("maze.in","r",stdin);
	freopen("maze.out","w",stdout);
	scanf("%d",&t);
	while(t--){
		scanf("%lf%d%d",&l,&n,&m);
		memset(a,0,sizeof(a));
		for(re i=1; i<=n; i++){
			for(re j=1; j<=m; j++){
				c = readc();
				if(c == ' ') continue;
				if(c == '#') a[i][j] = 1;
				if(c == 'S') sy=i,sx=j;
				if(c == 'E') ey=i,ex=j;
			}
		}
		printf("%.5f\n",bfs());
	}
	return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jack_Mask

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值