青蛙跳杯子(BFS)
#include <iostream>
#include <queue>
#include <string>
#include <unordered_set>
using namespace std;
int main() {
string a, b;
cin >> a >> b;
int n = a.size(); // 字符串长度
int d[] = {1, -1, -2, 2, -3, 3}; // 跳跃距离
queue<pair<string, int>> q; // 队列存储状态和步数
unordered_set<string> v; // 记录访问过的状态
q.push({a, 0}); // 初始状态入队,步数为0
v.insert(a); // 标记初始状态已访问
while (q.size()) {
auto [cur, step] = q.front(); // 取出当前状态和步数
q.pop();
int x = cur.find('*'); // 找到空杯子位置
// 尝试六种跳跃
for (int i = 0; i < 6; i++) {
int nx = x + d[i]; // 计算新位置
if (nx >= 0 && nx < n) { // 检查边界
string nt = cur; // 创建新状态
swap(nt[x], nt[nx]); // 执行跳跃
if (nt == b) { // 达到目标
cout << step + 1; // 输出步数
return 0;
}
if (v.find(nt) == v.end()) { // 未访问
q.push({nt, step + 1}); // 新状态入队
v.insert(nt); // 标记为已访问
}
}
}
}
return 0;
}
unordered_set:用于去重已访问状态。
cur.find('*'):返回字符串 cur 中 '*' 的索引。
string nt = cur:复制当前状态,避免修改 cur。
swap(nt[x], nt[nx]):交换 '*' 和目标位置的字符,模拟青蛙跳到空杯子。
if (nt == b):
- 如果新状态匹配目标状态,输出当前步数加 1(跳跃一步),退出程序。
if (v.find(nt) == v.end()):
- 检查 nt 是否在集合 v 中未出现(未访问)。
- find 返回迭代器,若等于 end(),表示未找到。
v 记录所有已访问的状态,例如:v = {"*WWBB", "W*WBB"}。
实例:
初始:
- a = "*WWBB", b = "WW*BB", n = 5
- q = {{"*WWBB", 0}}, v = {"*WWBB"}
第一步:
- cur = "*WWBB", step = 0, x = 0
- 尝试:
- nx = 1:nt = "W*WBB", 未匹配,入队 {{"W*WBB", 1}}, v = {"*WWBB", "W*WBB"}
- nx = -1:越界
- nx = -2:越界
- nx = 2:nt = "WW*BB", 匹配目标,输出 1, 退出