题目背景
pmshz在玩一个益(ruo)智(zhi)的小游戏,目的是打开九盏灯所有的灯,这样的游戏难倒了pmshz。。。
题目描述
这个灯很奇(fan)怪(ren),点一下就会将这个灯和其周围四盏灯的开关状态全部改变。现在你的任务就是就是告诉pmshz要全部打开这些灯。
例如
0 1 11 0 01 0 1点一下最中间的灯【2,2】就变成了
0 0 10 1 11 1 1再点一下左上角的灯【1,1】就变成了
1 1 11 1 11 1 1达成目标。最少需要2步。
输出2即可。
输入格式
九个数字,3*3的格式输入,每两个数字中间只有一个空格,表示灯初始的开关状态。(0表示关,1表示开)
输出格式
1个整数,表示最少打开所有灯所需要的步数。
输入输出样例
输入
0 1 1 1 0 0 1 0 1输出
2说明/提示
这个题水不水,就看你怎么考虑了。。。。
这道题其实就是一个搜索题,而且只有3*3个数据。
因为开灯这件事情,按钮按一下会发生变换,再按一下就复原了,相当于没有操作,所以最多每个按钮按一次,也就是最多也才就次。
我们只需要用一个深度优先搜索去试探开关灯,每次操作后去检查打开的灯数是否等于9(即是否达到目的全部打开)因为1代表开灯,0代表关灯,所以只需要遍历整个3*3的数组把值加起来判断是否等于9就可以判断了,如果达成了全开就更新一下最小值。
然后,开关灯的操作也非常简单,非常巧妙。
当当前为1时,用1-当前值=0,达成变换状态目的;
当当前值为0时,用1-当前值=1,达成变换状态目的。
我们再把按按钮封装为一个函数,可以让整体变得非常简单。
另外还有一点要提醒,就是按钮值不能大于9,如果大于9直接return,否则会死循环(虽然说这道题的数据不存在找不到方案的情况。)
AC代码:
#include<iostream>
using namespace std;
int a[5][5],ans=0,mni=10;
void fun(int x,int y)//按灯
{
//为1时,1-1=0,变换成功
//为0时,1-0=1,变换成功
//妙啊~~ovo
a[x][y]=1-a[x][y];
a[x+1][y]=1-a[x+1][y];
a[x][y+1]=1-a[x][y+1];
a[x-1][y]=1-a[x-1][y];
a[x][y-1]=1-a[x][y-1];
}
void dfs(int k)//搜索
{
if(k>mni)return;
int s=0;//开灯状态的灯数量
for(int i=1; i<=3; i++)//计算开灯的数量
for(int j=1; j<=3; j++)
s+=a[i][j];
if(s==9){//已达到全开状态,更新最小值
ans=k-1;
mni=min(ans,mni);
}
for(int i=1; i<=3; i++)
for(int j=1; j<=3; j++){
fun(i,j);
dfs(k+1);
fun(i,j);//回溯,再按一次等于没按,相当于回溯
}
return;
}
int main()
{
for(int i=1; i<=3; i++)
for(int j=1; j<=3; j++)
cin>>a[i][j];
dfs(1);//搜索
cout<<mni;
return 0;
}