洛谷 P2622 关灯问题II
题目描述
现有n盏灯,以及m个按钮。每个按钮可以同时控制这n盏灯——按下了第i个按钮,对于所有的灯都有一个效果。按下i按钮对于第j盏灯,是下面3中效果之一:如果a[i][j]为1,那么当这盏灯开了的时候,把它关上,否则不管;如果为-1的话,如果这盏灯是关的,那么把它打开,否则也不管;如果是0,无论这灯是否开,都不管。
现在这些灯都是开的,给出所有开关对所有灯的控制效果,求问最少要按几下按钮才能全部关掉。
输入格式
前两行两个数,n m
接下来m行,每行n个数,a[i][j]表示第i个开关对第j个灯的效果。
输出格式
一个整数,表示最少按按钮次数。如果没有任何办法使其全部关闭,输出-1
题解:
状压DP,练手。
刷表DP啦。
也就是一个状态可以用特别多的状态转移到的时候,可以刷表
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxx=1<<11;
int n,m;
int a[110][11];
int dp[maxx];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
memset(dp,127,sizeof(dp));
dp[(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]==1&&((now>>(k-1))&1))
now-=(1<<(k-1));
else if(a[j][k]==-1)
now|=(1<<(k-1));
}
dp[now]=min(dp[now],dp[i]+1);
}
if(dp[0]>10000000)
puts("-1");
else
printf("%d
",dp[0]);
return 0;
}