9509 开灯(dfs)

9509 开灯

时间限制:1000MS  内存限制:65535K
提交次数:0 通过次数:0

题型: 编程题   语言: G++;GCC

 

Description

有16的开关分别控制16盏灯,开关排列成4*4的矩形,这些开关有这样的关系:
你改变其中一个开关的状态,与其同行和同列的开关的状态也跟着改变。先给出一个这些开关的初始状态,要求将所有的开关都打开,让所有的灯都亮起来,要求按下开关的次数最少。




输入格式

第一行输入一个整数t,表示有多少个case,每个case之间有一空行,每个case输入一个0、1组成的4*4的矩阵,0表示开关状态为关,1表示开关状态为开。



输出格式

每个case输出一行,让所有灯都亮的最少按开关数。



 

输入样例

1
1011
1111
1111
1011



 

输出样例

6



 

提示

分别按下(1,1),(1,3),(1,4),(4,1),(4,3),(4,4)6个开关就行了
对于
1111
1011
1111
1111  
要把第二行和第二列的灯各按一次。

题解

从初始状态开始深搜,搜到灯全部亮着的状态时,更新最小步数,返回。

递归情况大概是这样

dfs(当前点,步数)

{

走到下一个灯;

if(找到状态)

{

更新最小步数;

return;

}

按一下当前的灯;

dfs(当前点,步数+1);

按一下当前的灯(和之前抵消,等于没按)

dfs(当前点,步数);

}

具体代码如下

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
char Map[5][5];
int map[5][5];
int minn;
int if_ok()//判断现在状态是否为灯全开的状态
{
    for (int i=0; i<4; i++)
        for (int j=0; j<4; j++)
            if (map[i][j]==0)
                return 0;
    return 1;
}
void change()//把原本字符型的改为整形,方便修改,也可以不要这步
{
    for (int i=0; i<4; i++)
        for (int j=0; j<4; j++)
            map[i][j]=Map[i][j]-'0';
}
void pull(int x,int y)//按一下当前的灯
{
    map[x][y]=1-map[x][y];
    for (int i=0; i<4; i++)
        map[i][y]=1-map[i][y];
    for (int i=0; i<4; i++)
        map[x][i]=1-map[x][i];
}
void dfs(int x,int y,int step)
{
    x++;
    if (x>=4)
    {
        y++;
        x=0;
    }
    if (y>=4)
        return;//从第一个等开始,走到最后一个结束
    pull(x,y);
    if (if_ok())
    {
        minn=min(minn,step+1);//更新最小步数
        return ;
    }
    dfs(x,y,step+1);
    pull(x,y);
    if (if_ok())
    {
        minn=min(minn,step);
        return ;
    }
    dfs(x,y,step);
}
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        minn=999999999;
        for (int i=0; i<4; i++)
            scanf("%s",Map[i]);
        change();
        dfs(-1,0,0);
        printf("%d\n",minn);
    }
    return 0;
}

 

 
posted @ 2016-05-31 22:41  酱油党gsh  阅读(341)  评论(0编辑  收藏  举报