POJ1753(广搜)

这是我第一篇博客,虽说是原创,但是是借着讲课时的PPT的思路敲的。如有雷同,不胜荣幸。
题目大意:有4*4的正方形,每个格子要么是黑色,要么是白色,当把一个格子的颜色改变(黑->白或者白->黑)时,其周围上下左右(如果存在的话)的格子的颜色也被反转,问至少反转几个格子可以使4*4的正方形变为纯白或者纯黑
思路:1、一共16个棋子最多翻转16次,翻两次和不翻是一样的;
       2、本题是求最小的步数所以用很标准的BFS那一套做就可以了,关键是状态的表示,算是加强了对BFS的印象
       3、而本题可以用二进制来表示2^16个状态,然后多有的操作用位运算来完成,
        右数第k位取反   x  ^ (1 << k),注意从第0位开始
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
using namespace std;

int vis[1<<16];
struct node {
    int val;
    int step;
};
int sta;
int bfs()
{
    queue<node> q;
    node t;
    t.step = 0;
    t.val = sta;
    q.push(t);
    vis[sta] = 1;
    while (!q.empty()) {
        node t = q.front();
        q.pop();
        if (t.val == 0 || (t.val == (1<<16) -1)) {
            cout << t.step << endl;
            return 1;
        }
        if (t.step >= 16) continue;//这应该算剪枝吧
        for (int i = 0; i < 16; i++) {//注意从0开始
            node tmp = t;
            tmp.step ++;
            tmp.val = tmp.val ^ (1<<(i));//下边画图就看出来了。
            if (i%4 != 0) tmp.val = tmp.val ^ (1<<(i-1));
            if ((i+1)%4 != 0) tmp.val = tmp.val ^ (1<<(i+1));
            if (i > 3) tmp.val = tmp.val ^ (1<<(i-4));
            if (i < 12) tmp.val = tmp.val ^ (1<<(i+4));
            if (!vis[tmp.val]) {
                q.push(tmp);
                vis[tmp.val] = 1;//注意标记,刚开始忘了,TLE一发
            }
        }
    }
    return -1;
}


int main()
{
    //freopen("input.txt", "r", stdin);
    char ch;
    sta = 0;
    scanf(" %c", &ch);//转化状态注意一共是左移15次
    if (ch == 'b') sta = 1;
    else sta = 0;
    for (int i =1; i < 16; i++) {
        scanf(" %c", &ch);
        if (ch == 'b') sta = (sta<<1)|1;
        else sta <<= 1;
    }
    memset(vis, 0,sizeof(vis));
    int ans = bfs();
    if (ans <= 0)puts("Impossible");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值