资源限制
时间限制:1.0s 内存限制:256.0MB
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及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。
----------------------------
笨笨有话说:
我梦见自己是一棵大树,
青蛙跳跃,
我就发出新的枝条,
春风拂动那第 5 层的新枝,
哦,我已是枝繁叶茂。
简介
当每一次操作的权值都是1时,像此类的最少操作,最短路等问题,显然BFS是一个不错的选择。每个状态的出现都能保证是通过最少的步骤第一次出现。需要利用队列,并且用结构体来构建状态。此题的状态主要是字符序列,当前位置,当前操作步数。
struct node {//利用结构体来表示状态
int x, step; //记录当前位置,和步数
string sn;//当前字符串序列
};
为了避免可能存在的重复序列,利用map来实现判断每个字符序列是否出现过。
map<string, int>mp; //判断该状态的字符串是否出现过,避免重复搜索
int是此字符串序列对应的值,1代表出现过,0代表没出现过。
创建队列后,初始状态入队,即先找到第一个空杯子的位置,只有结合空杯子才能进行跳跃。
queue<node>q;
now.sn = s1; now.step = 0;//初始状态
now.x = sx; mp[s1] = 1;//初始位置是第一个杯子的位置,标记初始字符序列,代表出现过
通过题干可知青蛙能做三种运动,因为动作无向,每种动作可前可后。所以应该是有6种跳法。青蛙能这么对着空杯子跳,所以也可以认为这空杯子能这样跳。不过在搜索过程中,不用判断跳的位置是否能跳。因为开始搜索的位置是空杯子,每次空杯子跳后,和对应位置交换,跳过去的位置成了空杯子。每次入队的位置都是空杯子的位置。而空杯子是一定能跳的,就算跳的位置也是空杯子,那便是相当于没跳,没跳的状态出现过,所以不会搜索。所以不用判断跳的位置是什么。
Code
#include <bits/stdc++.h>
using namespace std;
string s1, s2;
int minn, sx;//记录最小值和第一个空杯子
int dx[6] = { 1,2,3,-1,-2,-3 };//青蛙能做的三种动作,其实也相当于空杯子能这样。
map<string, int>mp; //判断该状态的字符串是否出现过,避免重复搜索
struct node {//利用结构体来表示状态
int x, step; //记录当前位置,和步数
string sn;//当前字符串序列
};
node now, t;//now为当前的状态,t为临时状态
void bfs() {
queue<node>q;
now.sn = s1; now.step = 0;//初始状态
now.x = sx; mp[s1] = 1;//初始位置是第一个杯子的位置
q.push(now);//入队
while (!q.empty()) {
now = q.front();//取出队首
q.pop();//出队
for (int i = 0; i < 6; i++) {//搜6个跳法
string s = now.sn;//s存储当前字符序列
int xx = now.x + dx[i];//xx记录跳的位置
if (xx >= 0 && xx < s1.length()) {//未越界
swap(s[now.x], s[xx]);//交换
if (mp[s] == 1) continue; //这种情况搜过,就跳过
mp[s] = 1;//标记
t.x = xx; t.step = now.step + 1;//记录新状态
t.sn = s;
if (t.sn == s2) {//如果达到了目标状态就结束搜索
minn = t.step;//因为每次状态一定是第一次出现,步数数最少的,所以直接返回
return;
}
//否则新状态入队继续搜索
q.push(t);
}
}
}
}
int main() {
cin >> s1 >> s2;
for (int i = 0; i < s1.size(); i++)
if (s1[i] == '*') {
sx = i; break;
}
bfs();
printf("%d", minn);
return 0;
}