openJudge 特殊密碼鎖 ACM

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

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

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

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

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

樣例輸出

1


首先先附上我AC的代碼:

#include<iostream>
#include<cstring>
using namespace std;

void change(char &a)
{
    if(a=='0') a='1';
    else if(a=='1') a='0';
    else return ;
}

int main()
{
    char a1[33],a2[33],b[33];
    cin>>a1;
    cin>>b;
    int n=strlen(a1);
    strcpy(a2,a1);
    int sum1=1,sum2=0;

    change(a1[0]);
    change(a1[1]);
    for(int i=0;i<n-1;i++)   //假設第一次按了第一個鍵
    {
        int j=i;
        if(a1[i]!=b[i])
        {
            sum1+=1;
            change(a1[++j]);
            change(a1[++j]);
        }
    }
    if(a1[n-1]!=b[n-1])
        sum1=-1;

    for(int i=0;i<n-1;i++)   //假設第一次未按第一個鍵
    {
        int j=i;
        if(a2[i]!=b[i])
        {
            sum2+=1;
            change(a2[++j]);
            change(a2[++j]);
        }
    }
    if(a2[n-1]!=b[n-1])
        sum2=-1;

    if(sum1 ==sum2 && sum1 == -1)    // 執行判斷
        cout<<"impossible";
    else
    {
        if(sum1 == -1 || sum2 == -1)
             cout<<(sum1 > sum2 ? sum1 : sum2);
        else
             cout<<(sum1 < sum2 ? sum1 : sum2);
    }
}

然後講一下我做這題的思路。

因爲題目中描述按一個鍵改變自身和相鄰的鍵。枚舉的時間複雜度太高,肯定是TLE,所以我採用的是貪心算法,保證前面的鍵先全部符合,再去看能否讓最後一個鍵匹配到,如果匹配就表示可行,輸出改變的次數sum。

用for循環的模式判斷a[i]與b[i]是否能對應,能對應就繼續。不能對應就改變a[i]後兩個鍵,這樣的做法相當於按了a[i+1],不用考慮a[i]本身的原因是直接i++就能跳過對a[i]的判斷。

然後提交。

WA。

回去看了下代碼,發現確實少考慮了一個情況。a[0]在題目中有特殊的地位——按下a[0]時僅改變之後的一個鍵,而改變a[0]的方法有兩種,一種是按a[0],另一種是按a[1],這兩種方法都不會影響之前數組的匹配。甚至說是先按a[0]、再按a[1]都能使a[0]保持原樣而影響之後的數組,所以不論a[0]與b[0]是否匹配,a[0]按和不按的情況都要考慮。

因此我把這種情況考慮進去。由於是change()是直接對數組中的數修改,所以我另開一個數組保存a,又另開一個sum統計變量。之後的判斷情況也進行了修改:如果第一次按了a[0],最後結果不能匹配則返回-1。

最後的輸出判斷也改成,如果兩個-1,那麼輸出impossible;哪個不是-1就輸出哪一個。(因爲這兩種情況不會同時實現)

修改完以後提交。

成功AC。

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