狀壓dp USACO 關燈問題Ⅱ
阿新 • • 發佈:2018-12-16
題意:盞燈,個按鈕,一開始所有燈都是亮的。按下按鈕對於第盞燈,是下面中效果之一:如果為,若此燈是亮的,把它關上,否則不管;如果為的話,若此燈是暗的,那麼把它開啟,否則也不管;如果是,無論這燈是否開,都不管。求關掉所有燈的最小操作次數。
狀壓dp經典開關燈問題,設表示燈處於狀態時需要的最小操作次數。因為燈一開始是全開的,所以我們從大到小列舉所有狀態,對於每一種狀態,列舉每一個按鈕和每一盞燈,我們設為此時的狀態,若並且第盞燈是亮的,即&,就改變此時的,即^,將該盞燈滅掉。當時也相同。最後,讓此次操作來更新答案。
#include<bits/stdc++.h>
using namespace std;
int n,m,f[100000],a[1000][1000];
int main()
{
cin>>n>>m;
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++j)
scanf("%d",&a[i][j]);
for(int i=0;i<(1<<n);++i)
f[i]=999999999 ;
f[(1<<n)-1]=0;
for(int i=(1<<n)-1;i>=0;--i)
{
for(int j=1;j<=m;++j)
{
int now=i;
for(int k=1;k<=n;++k)
{
if(a[j][k]==0)
continue;
if(a[j][k]==1&&(i&(1<<(k-1))))
now^=(1<<(k-1));
if(a[j][k]==-1&&!(i&(1<<(k-1))))
now^=(1<<(k-1));
}
f[now]=min(f[now],f[i]+1);
}
}
if(f[0]==999999999)
{
cout<<"-1";
return 0;
}
cout<<f[0];
return 0;
}