題目
感覺大佬們的**在讀入上的處理比本蒟蒻優秀多了,於是,乙個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,無論這燈是否開,都不...