洛谷 P2622 关灯问题II

洛谷 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;
}
原文地址:https://www.cnblogs.com/fusiwei/p/14085681.html