蓝桥杯国赛10-JavaB-8-大胖子走迷宫

package b10;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

/*
 * 小明是个大胖子,或者说是个大大胖子,如果说正常人占用 1 × 1 的面积,
小明要占用 5 × 5 的面积。
由于小明太胖了,所以他行动起来很不方便。当玩一些游戏时,小明相比
小伙伴就吃亏很多。
小明的朋友们制定了一个计划,帮助小明减肥。计划的主要内容是带小明
玩一些游戏,让小明在游戏中运动消耗脂肪。走迷宫是计划中的重要环节。
朋友们设计了一个迷宫,迷宫可以看成是一个由 n × n 个方阵组成的方阵,
正常人每次占用方阵中 1 × 1 的区域,而小明要占用 5 × 5 的区域。小明的位置
定义为小明最正中的一个方格。迷宫四周都有障碍物。
为了方便小明,朋友们把迷宫的起点设置在了第 3 行第 3 列,终点设置在
了第 n − 2 行第 n − 2 列。
小明在时刻 0 出发,每单位时间可以向当前位置的上、下、左、右移动单
位 1 的距离,也可以停留在原地不动。小明走迷宫走得很辛苦,如果他在迷宫
里面待的时间很长,则由于消耗了很多脂肪,他会在时刻 k 变成一个胖子,只
占用 3 × 3 的区域。如果待的时间更长,他会在时刻 2k 变成一个正常人,只占
用 1 × 1 的区域。注意,当小明变瘦时迷宫的起点和终点不变。
请问,小明最少多长时间能走到迷宫的终点
【输入格式】
输入的第一行包含两个整数 n,k。
接下来 n 行,每行一个由 n 个字符组成的字符串,字符为 + 表示为空地,
字符为 * 表示为阻碍物。
试题 H: 大胖子走迷宫 11
第十届蓝桥杯大赛软件类决赛 Java 大学 B 组
【输出格式】
输出一个整数,表示答案。
【样例输入】
9 5
+++++++++
+++++++++
++=++++++
+++++++++
+++++++++
***+*****
+++++++++
++++++=++
+++++++++
【样例输出】
16
 * */
public class T8_大胖子走迷宫 {
	
	static int y,x,k;
	
	static String[][] array;
	
	static int[][] dir = {
			{1,0},
			{-1,0},
			{0,1},
			{0,-1},
			{0,0}
	};
	
	static int f() {
		HashMap<String, Integer[]> map = new HashMap<>();
		
		int t = 0;
		int size = 5;
		
		Integer[] a = {2,2};
		map.put("2,2", a);
		
		while(true) {
			Set<String> set0 = map.keySet();
			Set<String> set = new HashSet<>();
			

			for (String key : set0) {
				set.add(key);
			}
			
			
			for (String key : set) {
				Integer[] a2 = map.get(key);
				
				int y0 = a2[0];
				int x0 = a2[1];
				
//				System.out.println(a2[0]);
				// 五种状态:上下左右不动
				// 达到最终状态
				if(y0==y&&x0==x) {
					return t;
				}
				
				// 确定跟随时间变化的尺寸
				if(t == k) {
					size = 3;
				}
				if(t == 2*k) {
					size = 1;
				}
				
				for (int i = 0; i < dir.length; i++) {
					int _y = dir[i][0];
					int _x = dir[i][1];
					
					// 确定边界距离中心间距
					int step = (size-1)/2;
					
					// 判断移动是否越界
					if(y0+_y-step<0||y0+_y+step==array.length||x0+_x-step<0||x0+_x+step==array[0].length) {
						continue;
					}
					
					
					// 判断移动之后是否有障碍物
					
					boolean can = true;
					
					outloop:
					for (int j = y0+_y-step; j <= y0+_y+step; j++) {
						for (int k = x0+_x-step; k <= x0+_x+step; k++) {
							if(array[j][k].equals("*")) {
								can = false;
								break outloop;
							};
						}
					}
					
					if(can) {
						Integer[] a3 = {y0+_y,x0+_x};
						map.put(a3[0]+","+a3[1], a3);

					}
					
				}
			}

			t++;
		}
		
	}
	
	public static void main(String[] args) {
		Scanner s = new Scanner(System.in);
		
		int n = s.nextInt();
		k = s.nextInt();
		s.nextLine();
		
		y = n-3;
		x = n-3;
		
		array = new String[n][];
		
		for (int i = 0; i < n; i++) {
			String str = s.nextLine();
			array[i] = str.split("");
		}
		
		System.out.println(f());
	}
}


/*
 * 思路:广度优先搜索,得到在t时刻内可能存在的位置和此时的大小size
 * 碰到问题:
 * 1.最开始使用深度优先搜索可能会在原地陷入死循环一直向下知道内存溢出
 * 2.广度优先搜索使用 List 或 stack 保存t时刻内可能处于的所有时刻,会有重复值存在例如不同的两个位置下一步可能会走到相同位置,采用 map 集合排除这种情况
 * 3.set集合是接口,不能使用Object的clone方法
 * 
 * */
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值