poj 1753 枚举+深搜

来源:互联网 发布:java log日志分析工具 编辑:程序博客网 时间:2024/05/20 18:45

题意:给一个4*4的矩阵,每个格非黑即白。选择翻动其中一个格的时候,它的上下左右同时也要翻过去,问最少翻几次可以把矩阵变成一样的颜色。

思路:每个格最多翻动一次(不算翻动其它格时把它也翻过去的情况),这样最多执行同样的操作16次,就可以得出结论。

这是我看到的写得比较清晰的代码,模块功能紧凑,我写了注释。转自:http://blog.sina.com.cn/s/blog_6635898a0100ivzv.html

1753Accepted704K204MSG++1146B

#include <iostream>using namespace std;bool map[6][6], findaaa = false;//map存矩阵中格的颜色,findaaa代表是否找到结果int step;//需要的步数int dr[5] = {-1, 0, 0, 0, 1};//dr和dc合起来代表每一个格和它周围的格的相对位置int dc[5] = {0, -1, 0, 1, 0};//分别为上(-1,0)、左(0,1)、中(自己)、右(0,1)、下(1,0)bool isgoal() {for(int i = 1; i<=4; ++i){for(int j = 1; j<=4; ++j){if(map[i][j] != map[1][1])//判断矩阵中的其它每一格是否都和第一个相同。{return false;}}}return true;}void flip(int row, int col){for(int i=0; i<5; ++i)//map的范围是[6][6]即[0-5][0-5],操作用到的是[1-4][1-4],不会越界{int r = row + dr[i];int c = col + dc[i];map[r][c] = !map[r][c];}}void dfs(int row, int col, int dep){if(dep == step){findaaa = isgoal();return;}if(findaaa || row == 5) return;flip(row, col);//给当前点执行flipif(col < 4) dfs(row, col + 1, dep + 1);else dfs(row + 1, 1, dep + 1);//如果列数超过4就换下一行,就是逐行深搜。flip(row, col);//如果没找到,把当前点翻回去,继续找下一个(此时dep就不 + 1了)。if(col < 4) dfs(row, col + 1, dep);else dfs(row + 1, 1, dep);}int main() {char c;for(int i = 1; i<=4; ++i){for (int j = 1; j<=4; ++j){cin >> c;if(c == 'b') map[i][j] = true;}}for(step = 0; step <= 16; ++step)//最多执行16步,一定能出结果{dfs(1, 1, 0);//从点(1,1)开始搜,初始化dep为0。if(findaaa) break;}if(findaaa)  cout << step << endl;else cout << "Impossible" << endl;return 0;}

这是我看到的比较快捷的代码,用了位操作,我写了注释,转自:http://www.cppblog.com/Yusi-Xiao/archive/2009/03/21/77383.html

1753Accepted936K47MSG++1868B

#include <iostream>#include <queue>#include <cstring>using namespace std;const int MAX_STATE = 65536;const int ALL_WHITE_STATE = 0;const int ALL_BLACK_STATE = 65535;const int WIDTH_OF_BOARD = 4;const int SIZE_OF_BOARD = WIDTH_OF_BOARD * WIDTH_OF_BOARD;int convertPieceColorToInt(char color)//把颜色转换成0、1整型{switch(color){case 'b': return 1;case 'w': return 0;}}int flipPiece(int state_id, int position){state_id ^= (1 << position);//异或操作^,相应位置的1换成0,0换成1.if(position -4 >= 0) state_id ^= (1 << (position - 4));//上边的格翻过去if(position + 4 < SIZE_OF_BOARD) state_id ^= (1 << (position + 4));//下if(position % 4 != 0) state_id ^= (1 << (position - 1));//左if(position % 4 != 3) state_id ^= (1 << (position + 1));//右return state_id;}int main() {int current_state_id = 0;int state[MAX_STATE];queue<int> search_queue;memset(state, -1, sizeof(state));char color;for (int i = 0; i<SIZE_OF_BOARD; ++i){cin >> color;current_state_id += convertPieceColorToInt(color) << i;//初始值,每一格的状态写到相应位置。}if(current_state_id == ALL_BLACK_STATE || current_state_id == ALL_WHITE_STATE){cout << "0" << endl;return 0;}state[current_state_id] = 0;//用来存需要的步数。search_queue.push(current_state_id);int next_state_id;while(!search_queue.empty())//用队列实现深搜,每次把相邻的点加入队列。{current_state_id = search_queue.front();search_queue.pop();for(int i = 0; i<SIZE_OF_BOARD; ++i){next_state_id = flipPiece(current_state_id, i);//再翻一个点i,结果为next_state_id。if(next_state_id == ALL_WHITE_STATE || next_state_id == ALL_BLACK_STATE){cout << state[current_state_id] + 1 << endl;return 0;}if(state[next_state_id] == -1)//如果没有出现过,就入队,值为当前点的值 + 1{state[next_state_id] = state[current_state_id] + 1;search_queue.push(next_state_id);}}}cout << "Impossible" << endl;return 0;}