歷屆試題 翻硬幣
時間限制:1.0s 內存限制:256.0MB
問題描述
小明正在玩一個“翻硬幣”的游戲。
桌上放着排成一排的若干硬幣。我們用 * 表示正面,用 o 表示反面(是小寫字母,不是零)。
比如,可能情形是:
**oo***oooo
如果同時翻轉左邊的兩個硬幣,則變為:
oooo***oooo
現在小明的問題是:如果已知了初始狀態和要達到的目標狀態,每次只能同時翻轉相鄰的兩個硬幣,那么對特定的局面,最少要翻動多少次呢?
我們約定:把翻動相鄰的兩個硬幣叫做一步操作,那么要求:
輸入格式
兩行等長的字符串,分別表示初始狀態和要達到的目標狀態。每行的長度<1000
輸出格式
一個整數,表示最小操作步數。
樣例輸入1
**********
o****o****
o****o****
樣例輸出1
5
樣例輸入2
*o**o***o***
*o***o**o***
*o***o**o***
樣例輸出2
1
貪心題。
我的思路是先對兩個字符串進行比較,用數組記錄下比較的結果,0表示字符相同,1表示字符不同。
用題目給的例子示范:
********** o****o****
比較結果為:
1000010000
翻動次數就是兩個1之間的下標之差。
當然也有些復雜的情況,若比較結果為:
101101100101
你是直接翻動中間的兩個“11”處的硬幣再解決其它硬幣呢(因為翻動相鄰的兩個硬幣只算一次操作),還是按上面的規則依次計算呢?
這道題“貪心”之處就在這里,事實上從左到右依次按上面藍字的規則累加計數,就可求得最優結果。
代碼如下:
1 #include <iostream>
2 using namespace std; 3 int main() 4 { 5 char s1[1000]; 6 char s2[1000]; 7 int cr[1000]; //記錄兩個字符串的比較結果。0為相同,1為不同。
8 while(cin>>s1){ 9 cin>>s2; 10 int l; 11 for(l=0;s1[l]!='\0';l++); //計算長度
12 for(int i=0;i<l;i++){ //比較兩個字符串,並記錄結果
13 if(s1[i]==s2[i]) 14 cr[i]=0; 15 else
16 cr[i]=1; 17 } 18 int f=-1; //記錄標記位
19 int _count=0; 20 for(int i=0;i<l;i++){ 21 if(cr[i]==1){ //檢測到一個 1
22 if(f==-1){ //如果前面沒有記錄的1的下標,記錄當前1的下標
23 f=i; 24 } 25 else{ //如果前面有一個1了
26 _count+=i-f; 27 f=-1; 28 } 29 } 30 } 31 cout<<_count<<endl; 32 } 33 return 0; 34 }
Freecode : www.cnblogs.com/yym2013
