首页 > 代码库 > Poj1753 翻转棋子

Poj1753 翻转棋子

这个题就是用枚举举遍所有情况,然后一个一个深搜看看是不是符合条件,符合条件直接退出,不符合则继续,

由于表格只有16个所以可以得知最多的步数只能是16,所以可以根据步数从0到16依次枚举,

第一个符合条件的就是最小的步数,为了容易深搜,可以设定顺序为一行一行深搜,当一行搜完时从下一行开头搜,

代码和测试数据如下:

#include<stdio.h>
int flag;
int step;
int map[4][4];


void turn(int i, int j) //转换
{
    map[i][j] = !(map[i][j]);
    if (i > 0)
    {
        map[i-1][j] = !(map[i-1][j]);
    }
    if (i < 3)
    {
        map[i + 1][j] = !(map[i + 1][j]);
    }
    if (j > 0)
    {
        map[i][j-1] = !(map[i][j-1]);
    }
    if (j < 3)
    {
        map[i][j + 1] = !(map[i][j + 1]);
    }
}



int range()//判定表格是否全部一样
{
    int i, j;
    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            if (map[i][j] != map[0][0])
            {
                return 0;
            }
        }
    }
    return 1;
}


int DFS(int i, int j, int dp)//深搜(dp<=step)
{
    //对第dp次的转换作判断
    if (dp == step)
    {
        flag = range();
        return 0;
    }
    if (flag || i == 4)
    {
        return 1;
    }

    //没有以上两种可以直接退出函数的情况,
    //说明此时的dp<step,就进行第dp+1次的转换
    turn(i, j);   

    //对第dp+1次的转换进行判断
    if (j < 3)
    {
        //判断的是第dp+1次时转换的turn(i,j),
        //如果判断成功,直接退出函数。
        //如果判断失败,要继续进行下一列(即j+1)的递归转换和判断
        //j+1不影响对第dp+1次转换的turn(i,j)的判断
        //因为在DFS()函数里,判断turn(i,j)的步骤总在turn(i,j+1)前面
        DFS(i, j+1, dp + 1);   
    }
    else
    {
        //判断的是第dp+1次时转换的turn(i,j),
        //如果判断成功,直接退出函数。
        //如果判断失败,要继续进行下一行(即i+1)的递归转换和判断
        //i+1不影响对第dp+1次转换的turn(i,j)的判断
        //因为在DFS()函数里,判断turn(i,j)的步骤总在turn(i+1,j)前面
        DFS(i + 1, 0, dp+1);
    }

    turn(i, j);      //不符合条件,重新转换回来


    //第dp次时,表格恢复初始状态
    if (j < 3)      
    {        
        DFS(i, j + 1, dp );   //进行对下一列进行第dp次的转换()
    }
    else
    {
        DFS(i + 1, 0, dp);    //进行对下一行进行第dp次的转换
    }

    return 0;

}


int main()
{
    char a;
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            scanf("%c", &a);
            if (a == b)
            {
                map[i][j] = 0;
            }
            else
            {
                map[i][j] = 1;
            }
        }
        getchar();    //不要遗忘
    }
    
    for (step = 0; step <= 16; step++)
    {
        flag = 0;
        DFS(0, 0, 0);
        if (flag)
            break;
    }
    if (flag)
    {
        printf("%d\n", step);
    }
    else
    {
        printf("Impossible\n");
    }

    return 0;

}

 

Poj1753 翻转棋子