#include <cmath>
#include <queue>
#include <cstring>
using namespace std;
const int statusNum = 1024*64;
char board[4][4];
char boardStatusColorMap[statusNum]; // For BFS, 0: white, 1: grey, 2: black
char boardLevelMap[statusNum];
// 1 xor 0 = 1, 1 xor 1 = 0, 0 xor 0 = 0, 1 xor 0 = 1
int flipOp[16] = {19, 39, 78, 140,
305, 626, 1252, 2248,
4880, 10016, 20032, 35968,
12544, 29184, 58368, 51200
}; // xor the boardIndex to get boardIndex after flip
bool noNeedFlip(int board) {
if (board == 0 || board == 65535) {
return true;
}
return false;
}
int getBoardId(char board[4][4]) {
int id = 0;
for (int i = 0; i <= 3; i++) {
for (int j = 0; j <= 3; j++) {
if (board[i][j] == 'b') {
id += pow(2, j + i*4);
}
}
}
return id;
}
void flipCertainPiece(int board, int *boardAfterFlip, int i, int j) {
board ^= flipOp[i + 4*j];
*boardAfterFlip = board;
}
int BFSFlip(int board) {
boardLevelMap[board] = 0;
queue<int> waitToSearchBoardQueue;
waitToSearchBoardQueue.push(board);
while(1) {
if (waitToSearchBoardQueue.size() == 0) {
return -1;
}
int waitToSearchboard = waitToSearchBoardQueue.front();
waitToSearchBoardQueue.pop();
for(int i = 0; i <= 3; i++) {
for (int j = 0; j <= 3; j++) {
int boardAfterFlit = 0;
flipCertainPiece(waitToSearchboard, &boardAfterFlit, i, j);
// if (waitToSearchboard == 14335) {
// printf("%d %d\n", boardAfterFlit, boardStatusColorMap[boardAfterFlit]);
// }
if (boardStatusColorMap[boardAfterFlit] == 0) {
waitToSearchBoardQueue.push(boardAfterFlit);
boardLevelMap[boardAfterFlit] = boardLevelMap[waitToSearchboard] +1;
boardStatusColorMap[boardAfterFlit] = 1;
// if (board == 14335 || board == 13709) {
// // printf("curId: %d pushedId: %d\n", board, boardAfterFlit);
// // printBoard(boardStatusMap[boardAfterFlipId]);
// }
if (noNeedFlip(boardAfterFlit)) {
// printf("curId: %d\n", curBoardId);
// printBoard(board);
// printBoard(boardStatusMap[boardAfterFlipId]);
return boardLevelMap[boardAfterFlit];
}
}
}
}
boardStatusColorMap[board] = 2;
}
}
int flip(char board[4][4]) {
int boardIndex = getBoardId(board);
if (noNeedFlip(boardIndex)) {
printf("0\n");
return 0;
}
int minStep = BFSFlip(boardIndex);
if (minStep == -1) {
printf("Impossible\n");
} else {
printf("%d\n", minStep);
}
}
int main() {
for(int i = 0; i < 4; i++) {
scanf("%s", *(board + i));
}
// board[0][0] = 'b';
// board[0][1] = 'w';
// board[0][2] = 'w';
// board[0][3] = 'b';
// board[1][0] = 'b';
// board[1][1] = 'b';
// board[1][2] = 'w';
// board[1][3] = 'b';
// board[2][0] = 'b';
// board[2][1] = 'w';
// board[2][2] = 'w';
// board[2][3] = 'b';
// board[3][0] = 'b';
// board[3][1] = 'w';
// board[3][2] = 'w';
// board[3][3] = 'w';
// 1001
// 1101
// 1001
// 1000
// board[0][0] = 'b';
// board[0][1] = 'w';
// board[0][2] = 'b';
// board[0][3] = 'b';
// board[1][0] = 'w';
// board[1][1] = 'w';
// board[1][2] = 'w';
// board[1][3] = 'b';
// board[2][0] = 'b';
// board[2][1] = 'w';
// board[2][2] = 'b';
// board[2][3] = 'w';
// board[3][0] = 'b';
// board[3][1] = 'b';
// board[3][2] = 'w';
// board[3][3] = 'w';
// board[0][0] = 'b';
// board[0][1] = 'b';
// board[0][2] = 'b';
// board[0][3] = 'b';
// board[1][0] = 'b';
// board[1][1] = 'b';
// board[1][2] = 'b';
// board[1][3] = 'b';
// board[2][0] = 'b';
// board[2][1] = 'b';
// board[2][2] = 'b';
// board[2][3] = 'w';
// board[3][0] = 'b';
// board[3][1] = 'b';
// board[3][2] = 'w';
// board[3][3] = 'w';
flip(board);
return 0;
}
基本思路BFS(自己竟然把BFS都给忘了... 还是需要练呀)。
1. 因为一开始搞成了错误的dfs,结果好几次TLE, 还以为是因为二位数组操作耗时,就又改成了直接用位异或运算来实现flip棋子的效果。
确实感觉时间提高了很多。也是一个很好的经验,位信息其实在很多情况下是可以代替数组的, 并且还直接hardcode了相应flip不同棋子对应要异或的值。
异或 1 -> 取反
异或 0 -> 不变。
2. stl queue在这时候就显出好用了, 不过要注意 front取值不删值, pop只能删值不取值.
3. 为了记录不同状态在dfs的level,又专门搞了一个数组记录,每次从某个状态遍历下面的状态时,直接在当前状态的level上 + 1. 应该有更好的办法吧。
4. 拓展的想,还可以要求求出每一步如何flip.
5. 对二维数组要再深化. 真正的工作,多是修补拓展,很多以前的知识,不用就忘了.
<====================================================================
#include <stdio.h>
#include <string.h>
#include <malloc.h>
typedef char CC[4][4];
typedef char (*DD)[4];
DD test() {
char (*a)[4] = (DD)malloc(16 * sizeof(char));
return a;
}
void test2(char foo[4][5]) {
printf("%d %d\n", (int)sizeof(foo), (int)sizeof(int*));
}
int main() {
test();
char foo[4][5];
char (*foo1) = foo[0];
foo1 = *foo;
foo1 = *(foo + 1);
printf("%d\n", (int)sizeof(foo));
test2(foo);
}
Output:
20
8 8
=======================================================================================>
以此为契机,把丢了很久的图论再看看.