切換
舊版
前往
大廳
主題

ZeroJudge - b297: 啊!殭屍 解題心得

Not In My Back Yard | 2019-10-09 22:50:50 | 巴幣 2 | 人氣 236

題目連結:


題目大意:
給定一正整數 N (N ≦ 10000000),代表有 N 隻殭屍。接著的一列有 N 個只會是 0 或是 1 的整數 a1 、 a2 、 ……、 aN ,代表第 i 隻(1 ≦ i ≦ N)殭屍的狀態。0 代表此殭屍是快速的;1 代表此殭屍為慢速殭屍。

手頭上有兩種藥劑槍,一個噴在第 i 隻,只會改變其狀態(快變慢,慢變快);另一個噴在第 i 隻,則會使得第 i - 1 、 i - 2 、…… 、 1 隻殭屍也都跟著改變狀態。

求要將所有殭屍變為慢速殭屍,最少需要噴幾次藥劑槍?



範例輸入:
#Sample Input 1
5
00100

#Sample Input 2
8
10001101

#Sample Input 3
10
1111111111


範例輸出:
#Sample Output 1
2

#Sample Output 2
3

#Sample Output 3
0


解題思維:
將 N 隻殭屍的序列倒過來看,變成 aN 、 aN - 1 、…… 、 a1 這個序列。例如範例測資的
8
10001101
會變成
10110001
因此,噴藥劑槍時能改變的殭屍變成是由左到右的,而非原本的由右到左。

因此,我們可以看到最佳的噴法是:
10110001
只改變第二隻(原本的倒數第二隻)的狀態
11110001
改變第五隻以後的狀態
111111110
最後,改變剩下的那一隻
111111111
總共噴了三次,所以所求為 3 。

而我們可以藉由掃過一次上述的序列,並用一個布林值紀錄當前殭屍其後(含自身)有無被前面的殭屍改動狀態過,即可找出所求,而不需真的一一翻轉狀態。

一樣以 10110001 為例,並跳過第一個字元先不看:
10110001
一開始碰到了 0 ,前一個字元是 1 ,不用改變狀態。
噴藥次數:0

10110001
接著是 1 ,前一個字元是 0 ,且前面沒有更動過。又因為只有一個 0 ,所以只須改動該隻殭屍的狀態。
噴藥次數:1

10110001
接著又一個 1 ,跟前一個字元一樣,因此跳過。

10110001
接著碰到了 0 ,上個連續序列內容為 11 、長度為 2 。因為前面沒有使後面更動狀態。因此 11 並不用處理。
噴藥次數:1

10110001
接著又一個 0 。與前字元一樣,因而跳過。

10110001
接著還是一個 0 。同理,跳過。

10110001
最後是 1 ,跟前面的字元不一致。因此判斷前面的連續序列 000 、長度 3 且沒有因為前面的噴藥而更動狀態。所以這邊的殭屍需要被噴藥,且是要噴範圍(長度 > 1)的所以會改變到後面的殭屍(也就是最後一個 1)。
噴藥次數:2

以上結束後還要再判斷最後的連續序列(在此例為最後一個單獨的 1 )該不該噴藥。因為前面的範圍噴藥,導致這邊被改變了狀態(如果前面噴了偶數次,則這邊會維持原樣;奇數則否),因此實際上該隻殭屍狀態為 0 。因此需要噴藥。

所以最後的噴藥次數為 3 ,即是所求。

此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。

創作回應

更多創作