问题描述
题目链接:青蛙跳杯子 资源限制
时间限制:1.0s 内存限制:256.0MB 问题描述 X星球的流行宠物是青蛙,一般有两种颜色:白色和黑色。
X星球的居民喜欢把它们放在一排茶杯里,这样可以观察它们跳来跳去。
如下图,有一排杯子,左边的一个是空着的,右边的杯子,每个里边有一只青蛙。
*WWWBBB
其中,W字母表示白色青蛙,B表示黑色青蛙,表示空杯子。 X星的青蛙很有些癖好,它们只做3个动作之一:
1. 跳到相邻的空杯子里。
2. 隔着1只其它的青蛙(随便什么颜色)跳到空杯子里。
3. 隔着2只其它的青蛙(随便什么颜色)跳到空杯子里。 对于上图的局面,只要1步,就可跳成下图局面:
WWWBBB
本题的任务就是已知初始局面,询问至少需要几步,才能跳成另一个目标局面。
输入为2行,2个串,表示初始局面和目标局面。
输出要求为一个整数,表示至少需要多少步的青蛙跳。
样例输入
WWBB
WWBB
样例输出
2
样例输入
WWWBBB
BBBWWW
样例输出
10
思路分析
思路代码参考:【蓝桥杯】历届试题 青蛙跳杯子(广度优先搜索bfs)
看到这道题的第一想法是想让青蛙去跳来实现,但这一思路无从下手。然后参考了上面这个,转换了思路:
我们不要以青蛙为主体去对字符串的空位进行位置交换,而是转而以空位(“*”)为主体,将题目转化为“有两个字符串“例如 *WWBB和WWBB,*每次能往左或右跳1-3步,与原位置的字符交换,问跳到第二个字符串的状态的最少步数”。
代码实现
#include <iostream>
#include <queue>
#include <cstring>
#include <set>
using namespace std;
int dir[]={-3,-2,-1,1,2,3}; //可移动的6种方案
struct situation{ //定义结构体:形势
string str; //当前形势下的字符串
int step; //得到当前形势的步数
situation(string s,int n)//构造函数
{
str=s,step=n;
}
};
queue <situation> q;
set <string> s;//每一步得到的所有字符串
void bfs(string start,string target)
{
if(start==target)
{
cout<<0<<endl;
return;
}
q.push(situation(start,0));
s.insert(start);
while(!q.empty())
{
situation now=q.front();//每次将要进行处理的形势放入now中
q.pop();
string str=now.str;//str表示当前进行处理的字符串
for(int i=0;i<str.length();i++)
{
if(str[i]!='*')continue;//仅对空杯子的位置进行换位
for(int j=0;j<6;j++)//对所有方案进行遍历
{
int n=i+dir[j];
if(n>=0&&n<str.length())//如果当前换位合法
{
swap(str[i],str[n]);//交换青蛙和当前空杯子的位置
if(str==target)//如果当前字符串等于目标字符串,则输出步数
{
cout<<now.step+1<<endl;
return;
}
if(!s.count(str))//如果当前字符串还未出现过
{
s.insert(str);//将之前未出现过的字符串放入s集合中
q.push(situation(str,now.step+1));
}
swap(str[i],str[n]);//恢复现场
}
}
}
}
}
int main()
{
string str1,str2;
cin>>str1>>str2;
bfs(str1,str2);
return 0;
}