解題日誌 - 關燈問題II(BFS+狀壓)

*關燈問題II(Luogu P2622)

先掛個連接 - https://www.luogu.com.cn/prob...c++

題面 - 現有N盞燈,M個按鈕。每一個按鈕能夠同時控制這n盞燈——按下某個按鈕,對於全部的燈都有一個效果。給出全部開關對全部燈的控制效果,問最少要按幾下按鈕能將燈從全開變爲全關數組

Now,進入正題spa

瞧下數據,N<=10,M<=100
數據規模不很大,果斷BFS(廣度優先搜索)
然而......
BFS的判重又成了大問題
逐個比對,看狀態是否一致,顯然超時
不判重,BFS就直接廢了設計

這時候,新Get到的技能——狀態壓縮閃亮登場
狀態壓縮即將原來狀態的數組存放變爲一個01構成的整數存放
這樣就這能夠設置一個下標表明狀態的vis[]數組來判重
判重瞬間降到O(1)級別
狀態的改變則用位運算,也降到O(1)級別code

就是這麼容易......ci

下面掛上程序(C++)和精心設計的註解方便理解get

//Luogu P2622 - 關燈問題II
//https://www.luogu.com.cn/problem/P2622
//BFS+狀壓 

#include <bits/stdc++.h> 
#define MAXN 2048 
using namespace std; 
 
int N, M; 

struct Node{ 
    int dp; //狀壓值,反應燈狀態 
    int step; //操做次數
}; 

int vis[MAXN]; //用於BFS的判重 
int a[MAXN][MAXN]; //燈的控制效果 

void BFS(int n){ 
    queue<Node> Q; 
    Node fir;
    fir.step = 0, fir.dp = n;
    Q.push(fir); 
    
    while(!Q.empty()){ 
       Node u=Q.front(); 
       Q.pop(); 
       int pre=u.dp; 
       //拿出隊首 
       
       for(int i=1; i<=M; i++){ 
          int now=pre; //now即爲狀壓值,燈的狀態 
          
          for(int j=1; j<=N; j++){ 
             if(a[i][j]==1){  
                if((1<<(j-1))&now){ 
                   now = now^(1<<(j - 1));
                } 
             } 
             else if(a[i][j]==-1){ 
                now = ( (1<<(j-1))|now);
                 
             } 
          } 
          //使用位運算改變狀壓值,反應了開關對於燈狀態的影響 
          
            fir.dp=now, fir.step=u.step+ 1;   
          
          if(vis[now]) continue; //BFS的判重 
          if(fir.dp==0){ 
             vis[0]=true;
             cout << fir.step << endl; 
             return ;
          }    
          //若是到達,輸出並退出BFS 
           
          Q.push(fir); //新狀態入隊 
          vis[now] = true; //記錄狀態,用於判重 
       } 
    } 
} 

int main(){ 
   cin >> N >> M; 
   int temp=(1<<(N))-1; 

   for(int i=1; i<=M; i++){ 
     for(int j=1; j<=N; j++){ 
        cin >> a[i][j]; 
     } 
   } 

   BFS(temp); 

   if(!vis[0]) 
     cout << -1 << endl; //沒法到達,輸出-1 

   return 0; 
}

這題最後的難點就是位運算了
其實筆者本身也有點懵......
往後筆者會潛心研究並撰寫相關專題的文章的
還請你們耐心等待it

若有疑問歡迎在評論區提出搜索

留個贊再走唄~程序

相關文章
相關標籤/搜索