算法基础:熄灯问题的思考

算法基础:北京大学

问题描述

Bilibili搬运地址:https://www.bilibili.com/video/av10046345/?p=4
建议如果视频第一遍没看懂,再看一遍就好了~.~

代码及注释

#include <stdio.h>

int puzzle[6][8], press[6][8];//分别在上,左,右添加一行或一列用于处理边界问题

//推测验证过程:
//根据第一行的情况,确定第二行的情况;然后用第二行的情况确定第三行,依次类推
bool guess() 
{
    int c, r;
    //用当前行的状态来确定下一行的状态,
    for(r=1; r<5; r++) 
    {
        for(c=1; c<7; c++) 
        {
            //这里有点巧妙,位置(r,c)按一下,一共会影响周边4个点
            //如果要使得(r,c)的值为0,那么在press(r,c)+press(r-1,c)+press(r+1,c)+press(r,c-1)+press(r,c+1)的按下的值要和puzzle(r,c)的值共奇偶
            //换句话说( press(r,c)+press(r-1,c)+press(r+1,c)+press(r,c-1)+press(r,c+1) )%2 == puzzle(r,c)
            //由于仅仅press(r+1,c)未知,因此把上式转换一下即可。
            press[r+1][c]=(puzzle[r][c]+press[r][c]+press[r-1][c]+press[r][c-1]+press[r][c+1])%2;
        }
    }

    //判断最后一行是否可用熄灭,如果不能说明第一行按错,需要重新枚举
    for(c=1; c<7; c++) 
    {
        if ((press[5][c-1]+press[5][c]+press[5][c+1]+press[4][c])%2 != puzzle[5][c])
        {
            return false;
        }
    }
    return true;
}


//枚举过程:
//对press第1行的元素press[1][1]~press[1][6]的各种取值进行枚举
//即对第一行各种可能的按键方式都进行枚举,这里用了二进制的思路进行枚举
void enumerate() 
{
    int c;
    for(c=1; c<7; c++) 
    {
        //第一个枚举情况,就是都不按
        press[1][c]=0;
    }
    while(guess()==false) 
    {
        press[1][1]++;
        c=1;
        //模拟二进制,即从000000->111111
        while(press[1][c]>1) 
        {  
            //累加进位
            press[1][c]=0;
            c++;
            press[1][c]++;
        }
    }
    return ;
}

int main() 
{
    int cases, i, r, c;
    scanf("%d", &cases);
    //初始化置零press
    for(r=0; r<6; r++) 
    {
        press[r][0]=press[r][7]=0;
    }
    for(c=0; c<7; c++) 
    {
        press[0][c]=0;
    }
    for(i=0; i<cases; i++) 
    {
        //注意这里循环从1开始,就是因为手工添加了一个边缘,要跳过
        for(r=1; r<6; r++) 
        {
            for(c=1; c<7; c++) 
            {
                scanf("%d", &puzzle[r][c]); //读入输入数据
            }
        }
        enumerate();
        printf("PUZZLE#%d\n", i+1);
        for (r=1; r<6; r++) {
            for (c=1; c<7; c++) {
                printf("%d ", press[r][c]);
            }
            printf("\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/u012348774/article/details/79866543