題解 P2622 關燈問題II

2022-03-28 20:03:33 字數 1664 閱讀 4318

題目

感覺大佬們的**在讀入上的處理比本蒟蒻優秀多了,於是,乙個afo蒟蒻弱弱地提出一下自己的看法

首先,對於 \(n\) 那麼小,肯定是狀壓啦

對於讀入,本蒟蒻開了兩個陣列來儲存每個按鈕的效果:\(open_i\) 和 \(close_i\) 分別表示在按下第 \(i\) 個按鈕後,它對於開著的開關和關閉的開關所造成的影響

那麼我們分開來想:

如果乙個狀態 \(set\) 中,為 \(1\) 的位表示開著的燈, \(0\) 表示關閉的

那麼,對於關閉的燈,如果 \(close_i\) 對它有影響,那麼一定是將它開啟

所以我們將 \(close_i\) 能影響到的燈的狀態直接打上 \(1\)

即如果開關效果為

1 0 -1 -1 0
那麼我們將 \(close_i\) 存為 \(00110_=6_\)

我們在使用它效果時則可以做到:

如果 \(set\bigcup close_i\),本身 \(close_i\) 中為 \(0\) 的位不影響

\(close_i\) 中本身為 \(1\) (即能影響到的位) 中,對於開著的,沒有影響,對於關閉的,造成影響並開啟

而對於 \(open_i\), 它的效果恰巧反過來,如果開著,則一定關閉

因此,我們將能影響到的燈的狀態打上 \(0\)

對於上面那組資料,我們將 \(open_i\) 存為 \(01111_=15_\)

使用時,我們就可以直接這麼做 \(set\bigcap open_i\)

這樣可以保證對於 \(open_i\) 中為 \(1\) 的位(即不能影響的位),不會造成影響

而對於會造成影響的位,如果本身是 \(0\) 的不會造成影響,而對於 \(1\) 的則關閉

完美地達到了要求

因此,我們初始化 \(close_i\) 為空集,\(open_i\) 為全集

如果讀入第 \(i\) 個開關第 \(j\) 個燈為 \(1\) ,則 \(open_i\) 去掉這一位,如果為 \(-1\) ,則 \(close_i\) 加上這一位

使用時,對於每個狀態 \(set\) ,和第 \(i\) 個開關,它們能達到的狀態就是 \(set\bigcup close_i\bigcap open_i\)

而對於最小步,直接 bfs 即可,詳情可以看本蒟蒻**

那本蒟蒻就放 我碼風極醜的 **了

#include#includeusing namespace std;

#define f(a,b,c) for(register int a=b;a<=c;a++)

#define g(a,b,c) for(register int a=b;a>=c;a--)

#define max(a,b) ((a>b)?a:b)

#define min(a,b) ((a'9')) neg^=!(c^'-'),c=getchar();

while((c>='0')&(c<='9')) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();

return neg?-ans:ans;

}//前面條件反射,莫管

int main()

} printf("%d",minn[0]);

return 0;

}

最後安利一下 本蒟蒻的部落格

P 2622 關燈問題

現有n盞燈,以及m個按鈕。每個按鈕可以同時控制這n盞燈 按下了第i個按鈕,對於所有的燈都有乙個效果。按下i按鈕對於第j盞燈,是下面3中效果之一 如果a i j 為1,那麼當這盞燈開了的時候,把它關上,否則不管 如果為 1的話,如果這盞燈是關的,那麼把它開啟,否則也不管 如果是0,無論這燈是否開,都不...

洛谷 P2622 關燈問題II

洛谷p2622 tag 狀態壓縮 題目大意 n個燈,m個按鈕,每個按鈕都可以控制所有燈,給出每個按鈕對每個燈的影響,求從全開到全關的最短步數。題目分析 每盞燈只有兩個狀態,即開與關,記為0和1,則所有燈的狀態總數為2 n n 3時,有000,001,010,100 對每個狀態單獨分析,可以把每個開關...

洛谷 P2622 關燈問題II

現有n盞燈,以及m個按鈕。每個按鈕可以同時控制這n盞燈 按下了第i個按鈕,對於所有的燈都有乙個效果。按下i按鈕對於第j盞燈,是下面3中效果之一 如果a i j 為1,那麼當這盞燈開了的時候,把它關上,否則不管 如果為 1的話,如果這盞燈是關的,那麼把它開啟,否則也不管 如果是0,無論這燈是否開,都不...