费解的开关
费解的开关
不得不说,这个开关真费解
这几天有点emo,沉不下心去看,连视频和题解都看不下去,后来去图书馆才好了点
现在想来,思路还是挺清晰的,最后提交错了三次,为啥呢,if的忘了加括号了,比对第三组数据才发现第34个灯有问题
下面是思路:
我们不难得到以下结论:
1.同一个开关按2下== 没按 按三下 == 按一下 => 每个开关至多按一下
2.如果一排一排来按的话,下面那排可以影响上面那排 => 这一排是否要按取决于上一排是否亮
那么由以上两个结论,我们可以得到以下思路:
首先对第一排进行全枚举
然后在第一排的各种情况下,根据 结论2 我们可以对第二排进行操作:如果这个灯的上一排不亮,那么点亮这个灯
然后每一排都这样操作
最后,遍历下最后一行,如果全亮,那么OK,反之无法点亮
途中记个数..然后.......
下面是代码:
//费解的开关
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
char a[5][5],b[5][5];
int n,ans=7;
void light(int x,int y)
{
int dx[5]={-1,0,0,0,1},dy[5]={0,-1,0,1,0};
for(int i=0;i<5;i++)
{
int ax=dx[i]+x,ay=dy[i]+y;
if(ax>=0&ax<5&ay>=0&ay<5)
a[ax][ay]^=1;
}
}
int work()
{
ans=7;
for(int k=0;k<1<<5;k++)//用来决定第一行每个开关是否该开
{
int res=0;
memcpy(b,a,sizeof(a));
for(int i=0;i<5;i++)
{
if((k>>i)&1)
{
light(0,i);
res++;
}
}
for(int i=0;i<4;i++)
{
for(int j=0;j<5;j++)
if(a[i][j]=='0')
{
light(i+1,j);
res++;
}
}
bool success=1;
for(int i=0;i<5;i++)
{
if(a[4][i]=='0')
{
success=0;
break;//就是这个,被我忘了放入括号....
}
}
if(success)
ans=min(ans,res);
memcpy(a,b,sizeof(a));
}
if(ans<=6)return ans;
return -1;
}
int main()
{
cin>>n;
while(n--)
{
for(int i=0;i<5;i++)
cin>>a[i];
cout<<work()<<endl;
}
return 0;
}
相关问题还有POJ的Painter's Problem
这类问题有四类解法...详情看知乎大佬的分析..
知乎点灯游戏分析
作者:qbning
-------------------------------------------
个性签名:曾经的我们空有一颗望海的心,却从没为前往大海做过真正的努力
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!