这个题就是用枚举举遍所有情况,然后一个一个深搜看看是不是符合条件,符合条件直接退出,不符合则继续,
由于表格只有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 ", step); } else { printf("Impossible "); } return 0; }