藍橋杯算法題解 歷屆試題 翻硬幣

題目描述

問題描述
小明正在玩一個“翻硬幣”的遊戲。
桌上放着排成一排的若干硬幣。我們用 * 表示正面,用 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章