【貪心算法】特殊的密碼鎖(openjudge8469)


a:特殊密碼鎖

總時間限制:
1000ms
內存限制:
1024kB
描述

有一種特殊的二進制密碼鎖,由n個相連的按鈕組成(n<30),按鈕有凹/凸兩種狀態,用手按按鈕會改變其狀態。

然而讓人頭疼的是,當你按一個按鈕時,跟它相鄰的兩個按鈕狀態也會反轉。當然,如果你按的是最左或者最右邊的按鈕,該按鈕只會影響到跟它相鄰的一個按鈕。

當前密碼鎖狀態已知,需要解決的問題是,你至少需要按多少次按鈕,才能將密碼鎖轉變為所期望的目標狀態。

輸入
兩行,給出兩個由0、1組成的等長字符串,表示當前/目標密碼鎖狀態,其中0代表凹,1代表凸。
輸出
至少需要進行的按按鈕操作次數,如果無法實現轉變,則輸出impossible。
樣例輸入
011
000
樣例輸出
    1

思路:看到輸入輸出首先想到的是枚舉所有按鈕的狀態,但是n的范圍為30,所以會有2的30次方多種,所以肯定不能枚舉出所有狀態,於是想了一個貪心策略,從左往右,如果按鈕不匹配就按下一個按鈕,始終讓左面的按鈕是匹配的,如果遍歷到最后一個按鈕不匹配則"impossible",否則輸出最少的按鈕次數。但是我忽略了一個特殊情況即前兩個按鈕,當前兩個按鈕不匹配時既可以按第一個按鈕也可以按第二個按鈕,所以應當考慮這兩種情況最后哪中情況按的次數少。由於我寫的代碼比較復雜,所以找了個大佬的代碼如下:

 

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string s,t,fin;
int tmp=0,ans=1e9,n;
/*字符串中'1'與'0'的轉換值得學習*/
inline void flip(int i){
    s[i-1]=s[i-1]=='1'?'0':'1';
    s[i]=s[i]=='1'?'0':'1';
    if(i+1<n) s[i+1]=s[i+1]=='1'?'0':'1';
}
int main(int argc, const char * argv[]) {
    cin>>s>>fin;t=s;
    n=s.size();
    //第一種情況:按鈕不匹配按后面的按鈕
    for(int i=1;i<n;i++)
        if(s[i-1]!=fin[i-1]){
            flip(i); tmp++;
        }
    if(s[n-1]==fin[n-1]) ans=tmp;
    //第二種情況:如果前兩個按鈕不匹配,按第一個按鈕,其他按鈕不匹配還是按后一個按鈕
    tmp=1;
    s=t;
    //原作者沒有加這個判斷,加上判斷代碼更清晰一些。
    if(s[0]!=fin[0]||s[1]!=fin[1]){
        s[0]=s[0]=='1'?'0':'1';
    s[1]=s[1]=='1'?'0':'1';
    for(int i=1;i<n;i++)
        if(s[i-1]!=fin[i-1]){
            flip(i); tmp++;
        }
    }

    //按完以后如果最后一個按鈕相同,則輸出兩種情況中的按的次數最少的情況。
    if(s[n-1]==fin[n-1]) ans=min(ans,tmp);
    //如果不同,則
    if(ans==1e9) cout<<"impossible";
    else cout<<ans;
    return 0;
}

 

 

 

 

 

代碼改自:http://www.cnblogs.com/candy99/p/5791488.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM