POJ_1753

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

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值