题目背景
pmshz在玩一个益(ruo)智(zhi)的小游戏,目的是打开九盏灯所有的灯,这样的游戏难倒了pmshz。。。
题目描述
这个灯很奇(fan)怪(ren),点一下就会将这个灯和其周围四盏灯的开关状态全部改变。现在你的任务就是就是告诉pmshz要全部打开这些灯。
例如 0 1 1
1 0 0
1 0 1
点一下最中间的灯【2,2】就变成了
0 0 1
0 1 1
1 1 1
再点一下左上角的灯【1,1】就变成了
1 1 1
1 1 1
1 1 1
达成目标。最少需要2步。
输出2即可。
输入输出格式
输入格式:
九个数字,3*3的格式输入,每两个数字中间只有一个空格,表示灯初始的开关状态。(0表示关,1表示开)
输出格式:
1个整数,表示最少打开所有灯所需要的步数。
输入输出样例
输入样例#1
0 1 1 1 0 0 1 0 1
输出样例#1
2
说明
这个题水不水,就看你怎么考虑了。。。。
思路
正如题目所说,水不水看你怎么考虑(我觉得很难)。本题dfs爆搜,具体看代码。
#include <stdio.h>
#include <iostream>
using namespace std;
int a[4][4],minx(1<<30),n(3);
int tox[6]={0,0,1,0,-1,0},toy[6]={0,0,0,1,0,-1};//自己,和4个方向
inline bool check()//检查是否灯都开了
{
register int i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(a[i][j]==0)
return 0;
}
}
return 1;
}
void dfs(int x,int y,int s)//s是当前解的开关次数
{
register int i,j,x1,y1;
if(s>minx)//如果当前次数比已知最小次数多
{
return;
}
if(check())//如果已经找到一个解
{
minx=s;
return;
}
if(x>n)//如果x边超边界
{
return;
}
if(y>=n)//如果y边超边界或即将超边界(这里以y边遍历3*3个点)
{
x1=x+1;//x下一行
y1=1;//y归1
}
else//如果y没超边界
{
x1=x;//还是x行
y1=y+1;//y+1
}//这些代码是尝试3*3个点的,直接for套for也行
dfs(x1,y1,s);//然后以这个再搜一次
for(i=1;i<=5;i++)//尝试5个方向
{
a[x+tox[i]][y+toy[i]]=1-a[x+tox[i]][y+toy[i]];//模拟开关
}
dfs(x1,y1,s+1);//以开过关的状态搜索
for(i=1;i<=5;i++)
{
a[x+tox[i]][y+toy[i]]=1-a[x+tox[i]][y+toy[i]];//再开关(回溯)
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=3;j++)
{
cin>>a[i][j];
}
}
dfs(1,1,0);
cout<<minx<<endl;
return 0;
}