注:該題目來自第四屆藍橋杯省賽c/c++ b組
題面如下:
小明正在玩乙個「翻硬幣」的遊戲。
桌上放著排成一排的若干硬幣。我們用 * 表示正面,用 o 表示反面(是小寫字母,不是零)。
比如,可能情形是:**oo***oooo
如果同時翻轉左邊的兩個硬幣,則變為:oooo***oooo
現在小明的問題是:如果已知了初始狀態和要達到的目標狀態,每次只能同時翻轉相鄰的兩個硬幣,那麼對特定的局面,最少要翻動多少次呢?
我們約定:把翻動相鄰的兩個硬幣叫做一步操作。
輸入格式
兩行等長的字串,分別表示初始狀態和要達到的目標狀態。
輸出格式
乙個整數,表示最小操作步數
資料範圍
輸入字串的長度均不超過100。
資料保證答案一定有解。
輸入樣例1:
**********
o****o****
輸出樣例1:5
輸入樣例2:*o**o***o***
*o***o**o***
輸出樣例2:1
這個題非常像「費解的開關」一題,不過比那個題**量要少不少,本題我的整體思路如下:首先,我們先用下圖所示的對應關係將對相鄰硬幣的翻轉操作歸結到結點上:
(我們假設a點是這個硬幣序列的開頭)
接下來我們來定義一種操作,叫做「翻轉操作」。
我們規定:如果a處發生一次「翻轉操作」,我們就會改變a和b兩枚硬幣的正反;如果b處發生一次「翻轉操作」,我們就會改變b和c兩枚硬幣的正反,以此類推
注意e處就不應該再有「翻轉操作」了,因為e硬幣只與d硬幣相鄰,而同時改變d和e兩枚硬幣的正反是d處發生「翻轉操作」的定義,所以在上圖中,實際上可能發生「翻轉操作」的只有n-1處
從上圖中,我們可以看到如果a處的硬幣正反狀態需要改變,我們必須執行a處硬幣的「翻轉操作」,因為沒有其他地方的「翻轉操作」能夠改變a處硬幣的狀態
而一旦確定下來a處的「翻轉操作」做或者不做,除了b處的「翻轉操作」以外,也就再沒有其他地方的「翻轉操作」可以改變b處硬幣的狀態了,以此類推,我們可以一直類推到d處
總結來說:i處的「翻轉操作」做不做取決於i-1處的「翻轉操作」結束後,i處的硬幣狀態是否正確;即i處的「翻轉操作」做與不做是出於保證i處的硬幣狀態正確的考慮
而對於末尾的e硬幣(它是第n枚硬幣,而我們的「翻轉操作」,它只到第n-1處),沒有後面的能保證它的狀態正確了
所以如果完整考慮,我們應該判斷一下e處硬幣的狀態是否正確:如果正確,我們就能夠把硬幣翻轉到目標狀態;否則就不能(但是題目保證有解了,所以就省事了hhh)
**就非常簡單了:o(n)掃過去就可以了
#include #include#include
#include
using
namespace
std;
intmain()
}cout
<< cnt <
return0;
}
藍橋杯 翻硬幣
問題描述 小明正在玩乙個 翻硬幣 的遊戲。桌上放著排成一排的若干硬幣。我們用 表示正面,用 o 表示反面 是小寫字母,不是零 比如,可能情形是 oo oooo 如果同時翻轉左邊的兩個硬幣,則變為 oooo oooo 現在小明的問題是 如果已知了初始狀態和要達到的目標狀態,每次只能同時翻轉相鄰的兩個硬...
藍橋杯 翻硬幣
小明正在玩乙個 翻硬幣 的遊戲。桌上放著排成一排的若干硬幣。我們用 表示正面,用 o 表示反面 是小寫字母,不是零 比如,可能情形是 oo oooo 如果同時翻轉左邊的兩個硬幣,則變為 oooo oooo 現在小明的問題是 如果已知了初始狀態和要達到的目標狀態,每次只能同時翻轉相鄰的兩個硬幣,那麼對...
藍橋杯翻硬幣
問題描述 小明正在玩乙個 翻硬幣 的遊戲。桌上放著排成一排的若干硬幣。我們用 表示正面,用 o 表示反面 是小寫字母,不是零 比如,可能情形是 oo oooo 如果同時翻轉左邊的兩個硬幣,則變為 oooo oooo 現在小明的問題是 如果已知了初始狀態和要達到的目標狀態,每次只能同時翻轉相鄰的兩個硬...