【bfs】【分支限界函数】【蓝桥杯】

【【【可能有代码是借鉴大神的,如果有问题会删掉并道歉!】】】

1.青蛙跳杯子

蓝桥杯 试题 历届试题 青蛙跳杯子

题目:http://lx.lanqiao.cn/problem.page?gpid=T448

package 练习;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

public class _44青蛙跳杯子_ {

	static String inStr,targetStr;
	static Map<String,Boolean> mapp=new HashMap<String,Boolean>();
	
	public static void main(String[] args) throws IOException {
        BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
        inStr = bReader.readLine();
        targetStr = bReader.readLine();
        bReader.close();
        System.out.println(bfs());
		
	}
    public static int bfs()
    {
    	//新建队列+新建头结点+头结点入队列+头结点标记hashmap
    	Queue<Node> queue =new LinkedList<Node>();
    	Node now = new Node(inStr,0);
    	queue.add(now);
    	mapp.put(now.string,true);
    	
    	//当队列非空
    	while(queue.size()!=0)
    	{
    		//头结点出队列
    		now=queue.poll();
    		//判断此时的结点是否满足最终的结果
    		if(isOk(now.string))
    		{
    			return now.step;
    		}
    		//当前头结点的一些信息
    		char s[]=now.string.toCharArray();
    		int stepp=now.step;
    		
    		//以now为头结点的各种情况(各个青蛙都跳)
    		for(int i=0;i<s.length;i++)
    		{
    			//杯子跳过
    			if(s[i]=='*')
    				continue;
    			//当前青蛙可跳的方向
    			for(int j=-3;j<=3;j++)
    			{
    				if(i+j<0||i+j>=s.length||j==0||s[i+j]!='*')
    					continue;
    				s=swap(s,i,i+j);
    				
    				Node node= new Node (String.valueOf(s),stepp+1); 
    				
    				if(!mapp.containsKey(node.string))
    				{
    					queue.add(node);
    					mapp.put(node.string,true);
    				}
    				//当前青蛙跳完要回归原样,下一个青蛙跳
    				s=swap(s,i,i+j);
    			}
    		}
    	}
		return -1;
    }
    
    public static char[] swap(char [] s,int i,int j)
    {
    	char temp;
    	temp=s[i];
    	s[i]=s[j];
    	s[j]=temp;
    	return s;
    }
    
    public static boolean isOk(String s)
    {
        if (targetStr.equalsIgnoreCase(s)) {
            return true;
        } 
        else {
            return false;
        }
    }
}

class Node
{
	String string;
	int step;
	public Node(String string,int step)
	{
		this.string=string;
		this.step=step;
	}
}
1.Map接口,HashMap实现,<k,v>
新建: Map<String,Boolean> mapp=new HashMap<String,Boolean>();
添加: mapp.put(now.string,true);
查询: mapp.containsKey(node.string)

2.队列, queue接口,LinkedList实现
新建: Queue<Node> queue =new LinkedList<Node>();
进队列: queue.add(now);
出队列: now=queue.poll();

3.字符数组
字符串变数组:char s[]=now.string.toCharArray();
数组变字符串:String str=String.valueOf(s)

2.九宫重排

题目:http://lx.lanqiao.cn/problem.page?gpid=T42

package 练习;

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

public class _19九宫重排_ {
	
	static String start,end,now;
	static Map<String,Integer> mapp=new HashMap<String,Integer>();
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		start = scan.next();
		end = scan.next();
		System.out.print(bfs());
	}
	
	public static int bfs()
	{
		//新建队列+头结点入队列+map记录
		Queue <String> queue=new LinkedList<String>();
		queue.add(start);
		mapp.put(start, 0);
		
		while(queue.size()!=0)
		{
			//头结点出队列
			now=queue.poll();
			//判断终止
			if (now.equals(end))
			{
				return mapp.get(now);
			}
			
			//处理头结点
			char s[]=now.toCharArray();
			
			int temp=0;
			int[] d = {-3,3,-1,1};//方向数组,分别表示上下左右
			for(int k=0;k<s.length;k++)
			{
				if(s[k]=='.')
				{
					temp=k;
					break;
				}
			}
			for(int i=0;i<4;i++)
			{
				//约束条件
				if(temp+d[i]<0||temp+d[i]>8||((temp+d[i])%3!=temp%3&&(temp+d[i])/3!=temp/3))
					continue;
				s=swap(s,temp,temp+d[i]);
				
				//判断新结点并入队列
				if(!mapp.containsKey(String.valueOf(s)))
				{
					mapp.put(String.valueOf(s), mapp.get(now)+1);
					queue.add(String.valueOf(s));
				}
				
				//恢复原字符串
				s=swap(s,temp,temp+d[i]);
			}
			
		}
		return 0;
	}
	public static char [] swap(char[] s,int i,int j)
	{
		char tempp;
		tempp=s[i];
		s[i]=s[j];
		s[j]=tempp;
		return s;
	}
}

1.这个bfs框架和上面那个基本相同
2.不同之处:用HashMap<k,v>里的value来记录步数,去掉了Node类
    取HashMap中的value值: mapp.get(now)
     (其中now为key值)
3.bfs能搜到所有结果,且第一次输出的结果为最小值(?)

3.学霸的迷宫

题目:http://lx.lanqiao.cn/problem.page?gpid=T291

package 算法提高;

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

public class _147学霸的迷宫 
{   static int a[][];
    //static int b[][]={{-1,0},{1,0},{0,-1},{0,1}};//这个顺序是不能随便调换的,是为了满足字典顺序的需求DLRU
    static int b[][]={{1,0},{0,-1},{0,1},{-1,0}};
    public static void main(String[]agrs)
    {       
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int m=sc.nextInt();
        a=new int[n][m];
        for(int i=0;i<n;i++)
        {
            String s=sc.next();
            for(int j=0;j<m;j++)
                a[i][j]=s.charAt(j)-'0';
        }//输入细节就不多讲了
        Queue<P> queue=new LinkedList<>();        //创建队列
        queue.add(new P(0,0,null,'n'));           //把第一个加入队列     加入起点,P这个类的信息见最下面
        a[0][0]=1;//置1说明不可访问;
        boolean sign=true;
        P tail=null;//指向终点
        while(!queue.isEmpty()&&sign)             //while
        {
            P p=queue.poll();//出一个头节点              //第一个出队列
            int x=p.x;
            int y=p.y;                            //对刚才出队列的点进行处理
            for(int i=0;i<4;i++)                  //for循环
            {
                int x1=x+b[i][0];                   
                int y1=y+b[i][1];
                if(x1<0||x1>=n||y1<0||y1>=m||a[x1][y1]==1)//排除不合理 continue
                    continue;
                a[x1][y1]=1;//这个要注意
                queue.add(new P(x1,y1,p,get(i)));          //把新点加入队列
                //x1,y1即为这点的位置信息,p即指向上一个节点,get(i)即为由p到当前点的方向
                if(x1==n-1&&y1==m-1)               //如果找到终点,则终止搜索
                {
                    tail=new P(x1,y1,p,get(i));//tail的作用
                    sign=false;//终止标志
                    break;//退出子循环
                }

            }
        }
        queue=null;
        Stack<P> stack=new Stack<>();
        P p=tail;
        while(p.last!=null)//从tail开始一个一个开始入栈;如果p.last为null则说明已经到了起点
        {
            stack.push(p);
            p=p.last;
        }
        System.out.println(stack.size());
        while(!stack.isEmpty())
        {
            System.out.print(stack.pop().d);//依次出栈即可
        }
    }
    static char get(int index)//满足字典顺序要求
    {
        switch(index)
        { 
        case 0:return 'D';
        case 1:return 'L';
        case 2:return 'R';
        case 3:return 'U';
        
        }
        return ' ';
    }
}
class P//实质上就是一个链表的node
{
    int x;
    int y;
    P last;//指向上一个位置,学c的可以看成是指针
    char d;//记录由上一个为到到当前位置的转向
    P(int x,int y,P last,char d)
    {
        this.x=x;
        this.y=y;
        this.last=last;
        this.d=d;
    }
}

4.迷宫

题目可见试题D:迷宫

package 第二次;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class _C迷宫 {
    static boolean[][] vis = new boolean[60][60];
	
	static HashSet <node> sets = new HashSet<node>();
	static int m=30,n=50;
	static char[][] mapp;

	public static void main(String[] args) throws FileNotFoundException {
		Scanner in = new Scanner (new File("/1.课程(项目相关)/蓝桥杯训练/2019A/maze.txt"));
		
		mapp= new char[m+1][n+1];
		for(int i=0;i<m;i++)
		{
			String temp=in.next();  //读取一行
			mapp[i]=temp.toCharArray();
		}
		bfs();
	}
	
	public static void bfs()
	{
		int zuobiao[][] = new int[][] {{1,0},{0,-1},{0,1},{-1,0}};
		String fangxiang[] = new String [] {"D","L","R","U"};
		int  newx,newy;
		
		Queue<node> que = new LinkedList<node>();  //建队列
		node first= new node(0,0,"",0);  
		que.add(first);   //头结点入队列

		while(que.size()!=0)
		{
			node now = que.peek();
			que.poll(); 
			vis[now.x][now.y]=true;
			if(now.x==m-1 && now.y==n-1)
			{
				System.out.print(now.path);
				return;
			}
			for(int i=0;i<4;i++)
			{
				newx=now.x+zuobiao[i][0];
				newy=now.y+zuobiao[i][1];
				
				if(newx<0||newy<0||newx>=m||newy>=n||mapp[newx][newy]=='1'||vis[newx][newy]==true)
				{
					continue;
				}
				node newnode = new node(newx,newy,now.path+fangxiang[i],now.step+1);
				que.add(newnode);
			}
		}
	}
}



class node
{
	String path;
	int step=0;
	int x,y;
	node(int x,int y ,String path,int step)
	{
		this.x=x;
		this.y=y;
		this.path=path;
		this.step=step;
	}
}

5.二叉树的层序遍历

链接

class Solution {

    public List<List<Integer>> resList = new ArrayList<List<Integer>>();

    public List<List<Integer>> levelOrder(TreeNode root) {
        checkFun02(root);

        return resList;
    }

    public void checkFun02(TreeNode node) {
        if (node == null) return;
        // 新建队列+头结点入队列
        Queue<TreeNode> que = new LinkedList<TreeNode>();
        que.offer(node);

        // 所有数据通过队列进行处理
        while (!que.isEmpty()) {
            // 通过len记录每一层
            // 对每一层进行处理,由于上一层已经都poll出去了,下一层还没开始,
            // 所以当前len就是本层数量
            List<Integer> itemList = new ArrayList<Integer>();
            int len = que.size();

            // 处理当前层
            while (len > 0) {
                // 本层节点相关处理:出队列,入结果列表
                TreeNode tmpNode = que.poll();
                itemList.add(tmpNode.val);

                // 下层结果预处理,进队列
                if (tmpNode.left != null) que.offer(tmpNode.left);
                if (tmpNode.right != null) que.offer(tmpNode.right);

                // 本层数量--
                len--;
            }

            //本层处理完了,放入结果列表
            resList.add(itemList);
        }

    }
}

6.二找树左下角的值

链接

class Solution {

    public int findBottomLeftValue(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int res = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode poll = queue.poll();
                if (i == 0) {
                    res = poll.val;
                }
                if (poll.left != null) {
                    queue.offer(poll.left);
                }
                if (poll.right != null) {
                    queue.offer(poll.right);
                }
            }
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值