POJ-1753 Flip Game(棋盘反转:BFS+状态压缩)
链接:http://poj.org/problem?id=1753
题目:通过翻转将4*4的棋盘转换为同一颜色
解题关键:当我们使用0或者1两种状态来表示棋子的黑色或者白色时,方格就可以被转化成一个16位的二进制状态数(用一个int32位就可以表示),而游戏完成正好对应这个数为0或者65535的状态。用位运算来模拟情况。
改进:针对棋盘较大的情况,采用最优解的情况。按照从上往下搜索的思路来进行,那么每一行的棋子翻转只会影响到上一行的棋子颜色。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<queue>
using namespace std;
bool visit[65540]; //记录每种情况是否已经出现,防止再次出现
int steps[65540];//用来记录steps
int exclusive(int state,int i) {
state ^= 1 << i;
if (i % 4 != 0) state ^= 1 << (i - 1);
if (i % 4 != 3) state ^= 1 << (i + 1);
if (i + 4 < 16) state ^= 1 << (i + 4);
if (i - 4 >= 0) state ^= 1 << (i - 4);
return state;
}
int BFS(int start) {
queue<int> q;
q.push(start);
visit[start] = 0;
steps[start] = 0;
while (!q.empty()) {
int now = q.front();
q.pop();
if (now == 0 || now==65535) {
return steps[now];
}
for (int i = 0; i < 16; i++) {
int state = exclusive(now, i);
if (visit[state] == 0) {
q.push(state);
visit[state] = 1;
steps[state] = steps[now] + 1;
}
}
}
return -1;
}
int main() {
memset(visit, false, sizeof(visit));//初始化
memset(steps, 0, sizeof(steps));
int state = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
state <<= 1;
char t;
scanf("%c", &t);
if (t == 'b')
state |= 1;
else
state |= 0;
}
getchar();
}
int res = BFS(state);
if (res == -1) {
printf("Impossible\n");
}else {
printf("%d\n", res);
}
return 0;
}
类似的题目【POJ-2965】开关:不同的地方在于每次变换是以行、列为一组,最终的状态只有一种。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
bool visit[65540];
int steps[65540];
int make[65540];
int front[65540];
queue<int> q;
int change(int state, int i) {
int row = i / 4;
int col = i % 4;
//行
for (int j = 0; j < 4; j++) {
state ^= (1 << (row * 4 + j));
}
//列
for (int j = 0; j < 4; j++) {
state ^= (1 << (j * 4 + col));
}
//自身
state ^= (1 << i);
return state;
}
int BFS() {
while (!q.empty()) {
int now = q.front();
q.pop();
if (now == 0) {
return steps[now];
}
for (int i = 0; i < 16; i++) {
int next=change(now,i);
if (visit[next] == 0) {
visit[next] = 1;
q.push(next);
steps[next] = steps[now] + 1;
front[next] = now;
make[next] = i;
}
}
}
}
int main() {
int state = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
char t;
state <<= 1;
scanf("%c", &t);
if (t == '+') {
state |= 1;
}else {
state |= 0;
}
}
getchar();
}
memset(visit, 0, sizeof(visit));
memset(steps, 0, sizeof(steps));
memset(front, -1, sizeof(steps));
q.push(state);
visit[state] = true;
steps[state] = 0;
printf("%d\n",BFS());
state = 0;
while (front[state] != -1) {
int i=make[state];
printf("%d %d\n", 4 - i / 4, 4 - i % 4);
state = front[state];
}
return 0;
}