POJ_1753

来源:互联网 发布:mac的办公软件 编辑:程序博客网 时间:2024/05/01 03:11

解题思路:关键是要理解,每个格子只有两种状态,而且最终翻转方法与格子被翻转的次序无关。

1. 位运算+BFS / BFS

2. 枚举:只要有一种枚举不满足,则其他枚举也不满足,反之,只要有一种枚举满足,则所有枚举都满足,因为同一个方块反转两次,整体不变,猜测所有的可行解都是可以相互转换,并且都始于全黑/白,终于全黑/白。

    http://poj.org/showmessage?message_id=165833(0ms,用进制枚举的方法很好,但是整体的方法不能确定是否正确,因为这题只有一个case,但是思路很好)。

3. 高斯消元法


代码:

1. ^的使用, 两次^等于本身,和翻转一样。

2. 每个棋子只有两种状态, 共2 ^ 16种, 可以用一个int表示,即状态压缩,然后BFS枚举所有的状态。

3. Flip()是对压缩状态的翻转+4, -4, +1, -1

4. 在BFS的时候,队列中保存状态和层数的二元组,要比在队列中每层压入哨兵高效和简单。

5. 使用位移直接input到压缩状态。

//280k  79ms#include <stdio.h>#include <stdlib.h>#include <string.h>#include <queue>#include <algorithm>using namespace std;int Flip(int cur, int pos) {  cur ^= (1 << pos);  if (pos + 4 < 16) cur ^= (1 << pos + 4);  if (pos - 4 >= 0) cur ^= (1 << pos - 4);  if (pos % 4) cur ^= (1 << pos - 1);  if (pos % 4 != 3) cur ^= (1 << pos + 1);  return cur;}int BFS(int board) {  if (board == 65535 || board == 0)    return 0;  queue<pair<int, int> > q;  bool visit[65536];  memset(visit, 0, sizeof(visit));  q.push(make_pair(board, 0));  visit[board];  while (q.size()) {    pair<int, int> pii = q.front();    q.pop();    int cur = pii.first;    for (int i = 0; i < 16; ++i) {      int next = Flip(cur, i);      if (next == 65535 || next == 0)        return pii.second + 1;      if (visit[next])        continue;      q.push(make_pair(next, pii.second + 1));      visit[next] = 1;    }  }  return -1;}int main() {  char piece;  int board = 0;  for (int i = 0; i < 4; ++i) {    for (int j = 0; j < 4; ++j) {      piece = getchar();      if (piece == 'b')        board |= (1 << (i * 4 + j));    }    getchar();  }  int res = BFS(board);  if (res == -1)    printf("Impossible");  else    printf("%d", res);  return 0;}


原创粉丝点击