列舉 1 熄燈問題

2022-06-13 07:27:09 字數 3109 閱讀 8072

題目描述:

有乙個由按鈕組成的矩陣,其中每行有6個按鈕,共5行。每個按鈕的位置上有一盞燈。當按下乙個按鈕後,該按鈕以及周圍位置(上、下、左、右)的燈都會改變一次。即,如果燈原來是點亮的,就會被熄滅;如果燈原來是熄滅的,則會被點亮。在矩陣角上的按鈕改變3盞燈的狀態;在矩陣邊上的按鈕改變4盞燈的狀態;其他的按鈕改變5盞燈的狀態。

如下圖所示,左圖表示燈的初始狀態為全亮,x表示按下操作,右圖表示按下後矩陣的狀態。

如下圖所示,當有相鄰兩個按鈕相繼按下時,對它們相鄰按鈕的狀態不發生變化。

對矩陣中的每棧燈設定乙個初始狀態,請你寫乙個程式,確定需要按下哪些按鈕,恰好使得所有的燈都熄滅。

根據上面的規則,我們知道:

1)第2次按下同乙個按鈕時,將抵消第1次按下時所產生的結果。因此,每個按鈕最多隻需要按下一次;

2)各個按鈕被按下的順序對最終的結果沒有影響;

3)對第1行中每盞點亮的燈,按下第2行對應的按鈕,就可以熄滅第1行的全部燈。如此重複下去,可以熄滅第1、2、3、4行的全部燈。

輸入:

第一行是乙個正整數n,代表需要解決的案例數。

每個案例5行組成,每一行包括6個數字(0或1)。相鄰兩個數字之間用單個空格隔開。0表示燈的初始狀態是熄滅的,1表示燈的初始狀態是點亮的。

輸出:

對於每個案例,首先輸出一行字串「puzzle #m」,其中m是該案例的序號。

5行組成,每一行包括6個數字(0或1)。相鄰兩個數字之間用單個空格隔開。其中的1表示需要把對應的按鈕按下,0則表示不需要按對應的按鈕。

樣例輸入:

0 1 1 0 1 0

1 0 0 1 1 1

0 0 1 0 0 1

1 0 0 1 0 1

0 1 1 1 0 0

樣例輸出:

1 0 1 0 0 1

1 1 0 1 0 1

0 0 1 0 1 1

1 0 0 1 0 0

0 1 0 0 0 0

---------------------

第一想法:

列舉所有可能的按鈕(開關)狀態, 對每個狀態,計算一下最後燈的情況, 看是否都熄滅。

每個按鈕有兩種狀態(按下或不按下),一共有30個開關, 那麼狀態數是230, 太多, 會超時 。

如何減少列舉的狀態數目呢?

基本思路: 如果存在某個區域性, 一旦這個區域性的狀態被確定, 那麼剩餘其他部分的狀態只能是確定的一種, 或者不多的n種, 那麼就只需列舉這個區域性的狀態即可。

1)因為第1行的各開關操作方案確定的情況下, 這些開關操作過後,將導致第1行某些燈是亮的, 某些燈是滅的。

要熄滅第1行某個亮著的燈(假設位於第i列), 那麼唯一的辦法就是按下第2行第i列的開關。(因為第1行的開關已經用過了, 而第3行及其後的開關不會影響到第1行)

為了使第1行的燈全部熄滅, 第2行的合理開關操作方案就是唯一的 。

2)第2行的開關操作過後,為了熄滅第2行的燈, 第3行的合理開關操作方案就也是唯一的。以此類推, 最後一行的開關操作方案也是唯一的。

只要第1行的操作方案定下來, 記作a, 那麼剩餘行的操作方案就是確定唯一的了 。

3)推算出最後一行的開關操作方案,然後看看最後一行的開關操作過後,最後一行的所有燈是否都熄滅:

如果是, 那麼a就是乙個解的狀態;如果不是, 那麼a不是解的狀態, 第1行換個狀態重新試試。、

問題簡化為:只需列舉第1行的操作方案, 狀態數是2^6 = 64 

有沒有狀態數更少的做法?

列舉第一列, 狀態數是2^5 = 32

實現方案:

把按鈕矩陣的第一行看作是乙個二進位制數,通過++來實現。

0 0 0 0 0 0

1 0 0 0 0 0

0 1 0 0 0 0

1 1 0 0 0 0 

0 0 1 0 0 0 

.......

1 1 1 1 1 1

具體實現:

使用乙個6*8的陣列來表示按鈕矩陣,因為對於原始的5*6的矩陣上

對於邊緣上的按鈕和中間的按鈕所影響的範圍是不一樣的,而我們想要簡化陣列下一行值的計算公式,所以多出來的第0行,0列,7列,不屬於原press矩陣範圍,可全置為0

用陣列元素 puzzle[i][j] 表示位置 (i, j) 上燈的初始狀態:1 表示燈是被點亮的;0 表示燈是熄滅的。

用陣列元素 press[i] [j] 表示為了讓全部的燈都熄滅,是否要按下位置 (i, j) 上的按鈕:1 表示要按下;0 表示不用按下。

因為燈的最後狀態(是否按它下一行開關之前)與周圍燈是否按按鈕有關,如 puzzle[i] [j],決定它最後狀態的相關按鈕為 press[i] [j-1] (左),press[i][j](它本身),press[i] [j+1](右),press[i-1][j](上),還有它最初的狀態 puzzle[i] [j]。考慮到按兩次按鈕作用會抵消,需要取它們的和與2的餘數,所以只要給定press的第一行的取值,其他行的值可以被相應的計算出來。

puzzle[i] [j] 最後狀態公式為:

press[i+1][j] = puzzle[i][j]最後狀態 = (press[i][j-1]+press[i][j]+press[i][j+1]+press[i-1][j]+ puzzle[i] [j] ) % 2

注:press[i+1] [j] 由 puzzle[i] [j] 的最後狀態決定,燈亮著(值為1)就要關掉它,press值取1,燈是熄滅的(值為0)不用處理,press值取0,它們是相等的,所以press[i+1] [j] = puzzle[i] [j] 最後狀態。

列舉 熄燈問題

有乙個由按鈕組成的矩陣,5行6列,每按一次改變原來顏色 具體事例如下圖所示 請寫乙個程式,判斷需要按哪些按鈕,能夠是燈泡全部熄滅。相關問題細節不再重複 剛剛輸入 2 0 1 1 0 1 0 1 0 0 1 1 1 0 0 1 0 0 1 1 0 0 1 0 1 0 1 1 1 0 0 0 0 1 0...

熄燈問題 列舉

1 問題描述 有乙個由按鈕組成的矩陣,其中每行有6個按鈕,共 5行。每個按鈕的位置上有一盞燈。當按下乙個按鈕後,該按鈕以及周圍位置 上邊 下邊 左邊 右邊 的燈都會改變一次。即,如果燈原來是點亮的,就會被熄滅 如果燈原來是熄滅的,則會被點亮。在矩陣角上的按鈕改變 3盞燈的狀態 在矩陣邊上的按鈕改變 ...

列舉 熄燈問題

問題描述 有乙個由按鈕組成的矩陣,其中每行有6個按鈕,共5行。每個按鈕的位置上有一盞燈。當按下乙個按鈕後,該按鈕以及周圍位置 上邊 下邊 左邊 右邊 的燈都會改變一次。即,如果燈原來是點亮的,就會被熄滅 如果燈原來是熄滅的,則會被點亮。在矩陣角上的按鈕改變3盞燈的狀態 在矩陣邊上的按鈕改變4盞燈的狀...