蓝桥杯中的BFS

1.青蛙跳杯子

【问题描述】
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

----------------------------

笨笨有话说:
    我梦见自己是一棵大树,
    青蛙跳跃,
    我就发出新的枝条,
    春风拂动那第 5 层的新枝,
    哦,我已是枝繁叶茂。

【问题分析】

        从一种状态到另一种状态,求需要的最小步数,这个时候就要想到可能会用到BFS求解。在数据结构的图遍历中,BFS是借助队列来实现的,但是图的节点都是固定的已知的。而在这个题目中,状态(点)是随机生成的。比如当前青蛙的状态使*wwbb,那么在这种状态下,所有可能的下一个串就相当于相邻的节点,然后将其入队列。

【代码展示】

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <queue>
#include <map>
#include <cmath>
#define INF 0x3f3f3f3f

using namespace std;
typedef long long ll;
const int MAXN = 20;
int dir[6]={-1,-2,-3,1,2,3};//定义青蛙可能跳跃的方向
//定义结构体 
struct Node{
	string s;//青蛙当前的状态 
	int step;//达到s这种状态所需要的步数 
	int pos;//"*"所在的位置 
	
	Node(string ss, int step1, int pos1){
		s=ss;
		step=step1;
		pos=pos1;
	} 
	Node(){
	}
}; 
queue<Node> myqueue;//定义队列
map<string,int> mymap;//防止状态重复 

string str,ans;//表示起始状态的字符串 

void BFS(){
	int len = str.size();//获取长度
	int pos = str.find('*');//获取'*'所在的位置
	Node p = Node(str,0,pos);//初始化表示青蛙开始状态信息的结构体
	myqueue.push(p);//入栈!
	mymap[str]=1;//记录已经存在
	while(!myqueue.empty()){//队列不为空 
		//
		Node temp;
		p = myqueue.front();//获取队头元素 
		myqueue.pop();//出队列
		if(p.s==ans){ //找到答案 
			cout<<p.step<<endl;//输出步数 
			return;
		}
		for(int i=0;i<6;i++){//后序节点是动态生成的!!!!! 
			temp.pos=p.pos+dir[i];//新状态中,*所在的位置 
			string s_temp=p.s;// 
			if(temp.pos<0||temp.pos>=len){
				continue;//不满足条件,重来 
			}
			swap(s_temp[temp.pos],s_temp[p.pos]);//青蛙跳哈哈哈哈哈哈
			temp.s=s_temp;//将新状态赋给
			temp.step=p.step+1;//步数加一
			if(mymap[temp.s]!=1){ //未出现过的状态才如队列 
				myqueue.push(temp);
				mymap[temp.s]=1;
			} 
		}
	} 
}

int main(){
	cin>>str>>ans;
	BFS();
} 
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值