一、问题背景与理解
洛谷P8597是一道经典的翻硬币问题,题目描述如下:给定两个由''和'o'组成的字符串s1和s2,分别表示初始状态和目标状态。每次操作可以选择任意位置开始翻转连续的k个硬币(''变'o','o'变'*')。要求计算出从初始状态变为目标状态所需的最少操作次数。
这个问题看似简单,但蕴含着重要的算法思想转变过程。作为新手,理解这个问题从暴力解法到最优解法的演进过程,对培养算法思维非常有帮助。
二、暴力BFS解法分析
int minOperations(string s, int k) {
int n = s.length();
int target = stoi(s, nullptr, 2); // 字符串转二进制数
queue<int> q; // BFS队列
vector<bool> visited(1<<n, false); // 状态访问标记
q.push(0); // 初始全0状态
visited[0] = true;
int steps = 0;
while (!q.empty()) {
int size = q.size();
while (size--) {
int curr = q.front();
q.pop();
if (curr == target) return steps;
for (int i=0; i<=n-k; ++i) {
int mask = (1<<k)-1 << i;
int next = curr ^ mask;
if (!visited[next]) {
visited[next] = true;
q.push(next);
}
}
}
steps++;
}
return -1;
}
三、贪心算法优化
#include <iostream>
#include <string>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s1, s2;
cin >> s1 >> s2;
int cnt = 0;
for (int i = 0; i < s1.size() - 1; ++i) {
if (s1[i] != s2[i]) {
// 翻转当前和下一个硬币
s2[i] = s1[i];
s2[i+1] = (s2[i+1] == 'o') ? '*' : 'o';
cnt++;
}
}
cout << cnt;
return 0;
}