P2622 關燈問題II (狀態壓縮入門)
阿新 • • 發佈:2018-12-16
題目連結: https://www.luogu.org/problemnew/show/P2622
具體思路:暴力,嘗試每個開關,然後看所有的情況中存不存在燈全部關閉的情況,在儲存所有燈的情況的時候,觀察到n的值不大,所以可以考慮用二進位制進行儲存,如果說這個數用二進位制表示的時候,如果第i位是1,代表第(i+1)個燈當前的狀態是開著的,否則就是關閉的.
AC程式碼:
#include<iostream> #include<cstring> #include<iomanip> #include<algorithm> #include<queue> #include<stdio.h> #include<cmath> using namespace std; # define inf 0x3f3f3f3f # define ll long long # define pi acos(-1.0) const int mod = 1e9 ; const int maxn = 200+100; struct node { int num; int step; node() {} node(int xx,int yy) { num=xx; step=yy; } }; int a[maxn][maxn]; int vis[6000],n,m; int bfs(int tot) { queue<node>q; vis[tot]=1; q.push(node(tot,0)); while(!q.empty()) { node top=q.front(); q.pop(); int t=top.num; for(int i=1; i<=n; i++) { int tmp=t; for(int j=1; j<=m; j++) { if(a[i][j]==1) { if(tmp&(1<<(j-1)))//如果說當前的燈是開著的,就改成關閉 tmp=tmp^(1<<(j-1)); } if(a[i][j]==-1) { tmp=tmp|(1<<(j-1));//改成開啟的狀態 } } if(vis[tmp])continue; vis[tmp]=1; q.push(node(tmp,top.step+1)); if(tmp==0) { return top.step+1; } } } return -1; } int main() { scanf("%d%d",&m,&n); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { scanf("%d",&a[i][j]); } } int tmp=(1<<m)-1;//初始狀態,每一位上都是1 int ans=bfs(tmp); printf("%d\n",ans); return 0; }