3 3 1 0 1 0 0 0 1 0 1
1
//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100000;
const int inf=(1<<28);
//有n*m的灯,最少几次可以把所有的灯点亮,每次可点周围5个 m<=20
int g[maxn],x[maxn];
int n,m;
int all;
int ans;
//计算n二进制中1的个数 分治思想 Matrix67博客有讲
int getOnesInN(int n)
{
n=(n&0x55555555)+((n>>1)&0x55555555);
n=(n&0x33333333)+((n>>2)&0x33333333);
n=(n&0x0f0f0f0f)+((n>>4)&0x0f0f0f0f);
n=(n&0x00ff00ff)+((n>>8)&0x00ff00ff);
n=(n&0x0000ffff)+((n>>16)&0x0000ffff);
return n;
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
memset(g,0,sizeof(g));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
//0暗 1亮
int tmp;scanf("%d",&tmp);
g[i]=(g[i]<<1)|tmp;
}
}
all=(1<<m)-1;
ans=inf;
for(int i=0;i<=all;i++)//枚举第一行开灯情况1,change;0,stay
{
for(int j=0;j<n;j++) x[j]=g[j];//用memcpy会超时
int cnt=getOnesInN(i);//开灯次数
//press 0 i
x[0]^=i,x[0]^=i<<1,x[0]^=i>>1;x[0]&=all;
x[1]^=i;
//2-n行已经确定
for(int j=1;j<n;j++)
{
int k=x[j-1]^all;//上一行0的位置
//press j,k
x[j]^=k,x[j]^=k<<1,x[j]^=k>>1;x[j]&=all;
x[j+1]^=k;
//
cnt+=getOnesInN(k);
}
if(x[n-1]==all) ans=min(ans,cnt);
}
if(ans==inf)printf("no solution\n");
else printf("%d\n",ans);
}
return 0;
}
解决灯光控制问题:最小点亮次数算法
本文探讨了一个在魔法房间中通过控制特定位置的灯泡,最小化点亮所有灯泡所需操作次数的问题。利用分治思想和二进制操作,文章详细介绍了算法实现过程及其实现代码。
463

被折叠的 条评论
为什么被折叠?



