题意:给一个4*4的矩阵,每个格非黑即白。选择翻动其中一个格的时候,它的上下左右同时也要翻过去,问最少翻几次可以把矩阵变成一样的颜色。
思路:每个格最多翻动一次(不算翻动其它格时把它也翻过去的情况),这样最多执行同样的操作16次,就可以得出结论。
这是我看到的写得比较清晰的代码,模块功能紧凑,我写了注释。转自:http://blog.sina.com.cn/s/blog_6635898a0100ivzv.html
1753 | Accepted | 704K | 204MS | G++ | 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);//给当前点执行flip
if(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
1753 | Accepted | 936K | 47MS | G++ | 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;
}