題目描述
現有n盞燈,以及m個按鈕。每個按鈕可以同時控制這n盞燈——按下了第i個按鈕,對於所有的燈都有乙個效果。按下i按鈕對於第j盞燈,是下面3中效果之一:如果a[i][j]為1,那麼當這盞燈開了的時候,把它關上,否則不管;如果為-1的話,如果這盞燈是關的,那麼把它開啟,否則也不管;如果是0,無論這燈是否開,都不管。
現在這些燈都是開的,給出所有開關對所有燈的控制效果,求問最少要按幾下按鈕才能全部關掉。
輸入輸出格式
輸入格式:
前兩行兩個數,n m
接下來m行,每行n個數,a[i][j]表示第i個開關對第j個燈的效果。
輸出格式:
乙個整數,表示最少按按鈕次數。如果沒有任何辦法使其全部關閉,輸出-1
輸入輸出樣例
輸入樣例#1: 複製32
1 0 1
-1 1 0
輸出樣例#1: 複製2說明
對於20%資料,輸出無解可以得分。
對於20%資料,n<=5
對於20%資料,m<=20
上面的資料點可能會重疊。
對於100%資料 n<=10,m<=100
使用dp 將問題所列的狀態用二進位制數來表示
1 表示燈開
0 表示燈關
列舉m個開關的狀態
以燈全開為起點進行列舉操作
《手打可能有誤
異或,與,或,好重要~(up up up
for
(int i=
1;i<=m;i++
)}
**~~ 感謝
ss&(1<< j-1)此運算用以檢查當前狀態的第j位是否為1
1<< j-1意思是將1左移j-1位,移動後只有第j位上是1
若開關操作為1且當前狀態第j位是1
則ss^=(1<< j-1) 表示 1與1異或後得0
若開關操作為-1且當前狀態第j位是0
則ss|=(1 << j-1) 表示 1或0 後得1 (此處異或操作也對,因為1異或0得1)
之後便用相同的方法在得到的每個狀態上再不斷搜尋每個狀態
由於是bfs,所以一旦某一步狀態表示為0(十進位制二進位制的0寫法都是0)
則當前步數必定是最短運算元
若遍歷完所有狀態都沒有0,則輸出-1
記得搜尋過的狀態要打vis標記避免重複訪問
#include
#include
#include
using
namespace std;
int n,m,cz[
150][20
];int vis[
1<<11]
;struct node
;int
bfs())
; vis[(1
<]=1;
int i,j;
while
(!q.
empty()
)int k;
for(i=
1;i<=m;i++)if
(!vis[k]))
;}}}
return-1
;}intmain()
}printf
("%d"
,bfs()
);}
第一次寫dp類的bfs ~
加油panda
洛谷 2622 關燈問題II
現有n盞燈,以及m個按鈕。每個按鈕可以同時控制這n盞燈 按下了第i個按鈕,對於所有的燈都有乙個效果。按下i按鈕對於第j盞燈,是下面3中效果之一 如果a i j 為1,那麼當這盞燈開了的時候,把它關上,否則不管 如果為 1的話,如果這盞燈是關的,那麼把它開啟,否則也不管 如果是0,無論這燈是否開,都不...
洛谷 P2622 關燈問題
輸入輸出樣例 說明切入正題 解 廣搜 手動分割 現有n盞燈,以及m個按鈕。每個按鈕可以同時控制這n盞燈 按下了第i個按鈕,對於所有的燈都有乙個效果。按下i按鈕對於第j盞燈,是下面3中效果之一 如果a i j 為1,那麼當這盞燈開了的時候,把它關上,否則不管 如果為 1的話,如果這盞燈是關的,那麼把它...
洛谷p2622 關燈問題
乙個比較典型的狀態壓縮演算法,不過現在還有點沒看懂。等留著以後再看.include include include include include includeusing namespace std int read while ss 0 ss 9 return f x void print in...