17年真题 蓝桥杯 javaC 青蛙跳 第九题-bfs(包含蓝桥杯 算法提高 学霸的迷宫-bfs)

17年真题 蓝桥杯 javaC 青蛙跳 第九题-bfs(包含蓝桥杯 算法提高 学霸的迷宫-bfs)

标题:青蛙跳杯子
X星球的流行宠物是青蛙,一般有两种颜色:白色和黑色。
X星球的居民喜欢把它们放在一排茶杯里,这样可以观察它们跳来跳去。
如下图,有一排杯子,左边的一个是空着的,右边的杯子,每个里边有一只青蛙。
WWWBBB
其中,W字母表示白色青蛙,B表示黑色青蛙,表示空杯子。
X星的青蛙很有些癖好,它们只做3个动作之一:
1. 跳到相邻的空杯子里。
2. 隔着1只其它的青蛙(随便什么颜色)跳到空杯子里。
3. 隔着2只其它的青蛙(随便什么颜色)跳到空杯子里。
对于上图的局面,只要1步,就可跳成下图局面:
WWW
BBB
本题的任务就是已知初始局面,询问至少需要几步,才能跳成另一个目标局面。
输入为2行,2个串,表示初始局面和目标局面。
输出要求为一个整数,表示至少需要多少步的青蛙跳。
例如:
输入:
WWBB
WWBB

则程序应该输出:
2
再例如,
输入:
WWW
BBB
BBB*WWW
则程序应该输出:
10
我们约定,输入的串的长度不超过15
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。

package javaC;

import java.util.*;

public class _9青蛙跳杯子_BFS {

	/**
	 * @param args
	 */
	
	static String str1;
	static String str2;
	static List<String> list = new LinkedList<String>();
    static Map<String, Boolean> vis = new HashMap<String, Boolean>();//用HashMap标记出现过的情况
	
    static class Node{
		int step = 0;
		String str;
		public Node(String str,int step){
			this.str = str;
			this.step = step;
		}
    }
    
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner input = new Scanner(System.in);
		str1 = input.next();
		str2 = input.next();
		
		System.out.println(bfs());
	}

	private static int bfs() {
		// TODO Auto-generated method stub
		Queue<Node> queue = new LinkedList<Node>();
		Node node = new Node(str1,0);//将初始状态加入到Node节点初始化
		queue.add(node);//然后再将改节点加入队列中
		vis.put(node.str, true);//再把该初始节点的状态用HashMap记录为已经使用过了
		while(queue.size()!=0){//如果队列的大小不为0
			node = queue.poll();//出队
			if(isOk(node.str))//判断这字符串是否与目标字符串相同
				return node.step;//返回跳到这一个字符串需要的次数
			
			char[] str = node.str.toCharArray();//将出队列的这个节点中的str字符串转换成字符数组
			int step = node.step;//获取这一字符串的步数
			for(int i=0;i<str.length;i++){//遍历这个字符串
				if(str[i]=='*') continue;//遍历到'*',跳过这个,继续下一个循环
				for(int j=-3;j<=3;j++){//青蛙跳空杯有6种情况,左3,左2,左1,右1,右2,右3,遍历这六种情况
					if(i+j<0 || i+j>=str.length || j==0 || str[i+j]!='*') continue;//判断遍历越界,跳过这个,继续下一个循环
					str = swap(str,i,j);//青蛙跳空杯,交换str串的i和j字符,再将此新字符串赋给str字符串
					node = new Node(String.valueOf(str),step+1);//将这个新的字符串,步数+1,初始化一个新节点
					if(!vis.containsKey(node.str)){//判断这个新的字符串以前是否出现过
						queue.add(node);//没有出现过,将这个node节点加入队列
						list.add(node.str);//将node.str加入list中
						vis.put(node.str, true);//设置这个字符串已经出现过
					}
					str = swap(str,i,j);//出现过,将字符串复原,继续循环
				}
			}
		}
		
		return -1;//如果队列为0,还没出现目标字符串,返回-1
	}                                                                  

	private static char[] swap(char[] str, int i, int j) {
		// TODO Auto-generated method stub
		char temp = str[i];
		str[i] = str[j+i];
		str[j+i] = temp;
		return str;
	}
	
	//判断str和目标字符串str2是否相同
	private static boolean isOk(String str) {
		// TODO Auto-generated method stub
		if(str2.equalsIgnoreCase(String.valueOf(str)))
			return true;
		else
			return false;
	}
	
}


试题 算法提高 学霸的迷宫
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
  学霸抢走了大家的作业,班长为了帮同学们找回作业,决定去找学霸决斗。但学霸为了不要别人打扰,住在一个城堡里,城堡外面是一个二维的格子迷宫,要进城堡必须得先通过迷宫。因为班长还有妹子要陪,磨刀不误砍柴功,他为了节约时间,从线人那里搞到了迷宫的地图,准备提前计算最短的路线。可是他现在正向妹子解释这件事情,于是就委托你帮他找一条最短的路线。
输入格式
  第一行两个整数n, m,为迷宫的长宽。
  接下来n行,每行m个数,数之间没有间隔,为0或1中的一个。0表示这个格子可以通过,1表示不可以。假设你现在已经在迷宫坐标(1,1)的地方,即左上角,迷宫的出口在(n,m)。每次移动时只能向上下左右4个方向移动到另外一个可以通过的格子里,每次移动算一步。数据保证(1,1),(n,m)可以通过。
输出格式
  第一行一个数为需要的最少步数K。
  第二行K个字符,每个字符∈{U,D,L,R},分别表示上下左右。如果有多条长度相同的最短路径,选择在此表示方法下字典序最小的一个。
样例输入
Input Sample 1:
3 3
001
100
110
Input Sample 2:
3 3
000
000
000
样例输出
Output Sample 1:
4
RDRD
Output Sample 2:
4
DDRR
数据规模和约定
  有20%的数据满足:1<=n,m<=10
  有50%的数据满足:1<=n,m<=50
  有100%的数据满足:1<=n,m<=500。

package 算法提高;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class 学霸的迷宫_BFS {

	/**
	 * @param args
	 */
	
	public static int[][] move = {{-1,0},{1,0},{0,-1},{0,1}};//表示上下左右
	public static String[] onePath = {"U","D","L","R"};//表示上下左右
	
	static class point{//内部类
		int x;//当前顶点的横坐标
		int y;//当前顶点的纵坐标
		int step;//行走到当前顶点的步数
		String path;//行走到当前顶点的具体路径
		point(int x,int y,int step,String path){
			this.x = x;
			this.y = y;
			this.step = step;
			this.path = path;
		}
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner input = new Scanner(System.in);
		int n = input.nextInt();
		int m = input.nextInt();
		input.nextLine();
		String[] A = new String[n];
		for(int i=0;i<n;i++){
			A[i] = input.next();
		}
		bfs(A,m);
	}

	private static void bfs(String[] A, int m) {
		// TODO Auto-generated method stub
		int[][] matrix = getMatrix(A,m);
		Queue<point> queue = new LinkedList<point>();
		queue.add(new point(1,1,0,""));//表示从顶点(1,1)出发
		int minStep = Integer.MAX_VALUE;//用于记录到达最终顶点所需最少步数
		String minPath = "";//用于记录到达最终顶点路径的最小字典序序列
		while(queue.size()!=0){
			point begin = queue.poll();//第一个元素出队
			if(begin.x == matrix.length-1 && begin.y == matrix[0].length-1){//这个位置是终点
				if(minStep > begin.step){//如果minStep>begin.step,获取最小step和最小path
					minStep = begin.step;
					minPath = begin.path;
				}
				else if(minStep == begin.step){//如果步数相同,获取字典序最小
					if(judge(minPath,begin.path))//若minPath>begin.path的字典序
						minPath = begin.path;//把begin.path赋给minPath
				}
				System.out.println(minStep+"\n"+minPath);//找到最优结果,输出
				return;
			}
			for(int i=0;i<4;i++){
				int x = begin.x + move[i][0];
				int y = begin.y + move[i][1];
				int step = begin.step + 1;
				String path = begin.path + onePath[i];
				point temp = new point(x,y,step,path);
				if(check(matrix,temp)){//判断这个顶点temp是可到达的顶点时
					queue.add(temp);
					matrix[x][y] = 1;//到达该顶点后,标记该顶点不可到达
				}
			}
			
		}
		
		return;
	}

	//判断这个位置是否可以到达
	private static boolean check(int[][] matrix, point temp) {
		// TODO Auto-generated method stub
		int n = matrix.length-1;
		int m = matrix[0].length-1;
		if(temp.x<1 || temp.x>n || temp.y<1 || temp.y>m || matrix[temp.x][temp.y]==1)
			return false;
		return true;
	}

	//判断最小字典序
	private static boolean judge(String A, String B) {
		// TODO Auto-generated method stub
		char[] arrayA = A.toCharArray();
		char[] arrayB = B.toCharArray();
		for(int i=0;i<A.length();i++)
			if(arrayA[i] < arrayB[i])
				return false;
		return true;
	}
	
	//将字符串数组,转换成int类型的数组
	private static int[][] getMatrix(String[] A, int m) {
		// TODO Auto-generated method stub
		int[][] matrix = new int[A.length+1][m+1];
		for(int i=0;i<A.length;i++){
			char[] arrayA = A[i].toCharArray();
			for(int j=0;j<m;j++){
				matrix[i+1][j+1] = arrayA[j]-'0';
			}
		}
		return matrix;
	}

}

ps:由于之前没怎么用过bfs,这一次第一次正式用到bfs算法,不太会,所以参考了别博主的代码,然后又从蓝桥杯练习系统上找了一个类似的题目摸索了一下。感觉有一点点略懂了,但是还是很生疏,所以特此记录下来,方便后面学习的时候查阅。
pps:因为不太会,所以注释写的有点多QAQ

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值