蓝桥杯算法题解 历届试题 翻硬币

题目描述

问题描述
小明正在玩一个“翻硬币”的游戏。
桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。
比如,可能情形是:oo*oooo
如果同时翻转左边的两个硬币,则变为:oooo***oooo
现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?
我们约定:把翻动相邻的两个硬币叫做一步操作。

输入格式
两行等长的字符串,分别表示初始状态和要达到的目标状态。每行的长度<1000

输出格式
一个整数,表示最小操作步数。

样例输入1


oo
样例输出1
5
样例输入2
ooo***
ooo***
样例输出2
1

题解

这道题说是贪心,但我总感觉对应到题解,这两字很模糊(可能是我还理解的不够好),题解: 比较两个字符串,发现有不相同的字符(s[i] != e[i]),就将s的i和i+1翻转,然后继续从i=0比较,直到两个字符串相等,记录翻转次数。
**但是其实我也不知道怎么证明:这样的翻转次数就是最小的? **

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <deque>
#include <list>
#include <utility>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <bitset>
#include <iterator>
using namespace std;

typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll  INF = 0x3f3f3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double E = exp(1.0);
const int MOD = 1e9+7;
const int MAX = 1e5+5;

string s,e;
int len;
int num;

void reverseStr(int i)
{
    //cout << endl << "翻转前:" + s << endl;
    if(s[i] == 'o')
    {
        s[i] = '*';
    }
    else
    {
        s[i] = 'o';
    }

    if(s[i+1] == 'o')
    {
        s[i+1] = '*';
    }
    else
    {
        s[i+1] = 'o';
    }
    //cout << "翻转后:" + s << endl;
}

int main()
{
    /*
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    */
    cin >> s >> e;
    int i = 0;
    len = s.length();
    while(i < len)
    {
        //cout << i << " ";
        if(s[i] != e[i])
        {
            reverseStr(i);// 翻转字符串s的i和i+1位置的字符
            num++;
            i = 0;// 重新从开始比较
        }
        else
        {
            i++;
        }
    }
    cout << num << endl;

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章