poj1753-Flip Game BFS+位运算

题目大意:有一个4*4的方格,每个方格中放一粒棋子,这个棋子一面是白色,一面是黑色。游戏规则为每次任选16颗中的一颗,把选中的这颗以及它四周的棋子一并反过来,当所有的棋子都是同一个颜色朝上时,游戏就完成了。现在给定一个初始状态,要求输出能够完成游戏所需翻转的最小次数,如果初始状态已经达到要求输出0。如果不可能完成游戏,输出Impossible。

主要思想:

1.如果用一个4*4的数组存储每一种状态,不但存储空间很大,而且在穷举状态时也不方便记录。因为每一颗棋子都只有两种状态,所以可以用二进制0和1表示每一个棋子的状态,则棋盘的状态就可以用一个16位的整数唯一标识。而翻转的操作也可以通过通过位操作来完成。显然当棋盘状态id为0(全白)或65535(全黑)时,游戏结束。

2.对于棋盘的每一个状态,都有十六种操作,首先要判断这十六种操作之后是否有完成的情况,如果没有,则再对这十六种操作的结果分别再进行上述操作,显然这里就要用到队列来存储了。而且在翻转的过程中有可能会回到之前的某种状态,而这种重复的状态是不应该再次入队的,所以维护Vis[i]数组来判断id==i的状态之前是否已经出现过,如果不是才将其入队。如果游戏无法完成,状态必定会形成循环,由于重复状态不会再次入队,所以最后的队列一定会是空队列。

3.由于0^1=1,1^1=0,所以翻转的操作可以通过异或操作来完成,而翻转的位置可以通过移位来确定

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
#define Max 65535
int queue[Max*2];                 //BFS算法中的队列
int step[Max];                   //记录是翻第几次
int vis[Max];                   //记录是否翻过这种状态
int tab=0;                     //记录是否能翻成功
void bfs(int s){
    int head=0,rear=0;
    step[s]=0;
    if(s==0||s==Max){
        printf("%d\n",0);
        tab=1;
        return;
    }
    queue[rear++]=s;
    vis[s]=1;
    while(head<rear){
        int temp=queue[head++];
        int t=temp;
        for(int i=0;i<16;i++){
            temp=t;              //为下一次翻棋子保护状态
            temp^=1<<(15-i);
            int tm;
            int label=15-i;
            tm=label+4;            //处理上边的棋子
            if(tm!=19&&tm!=18&&tm!=17&&tm!=16)
                temp^=1<<tm;
            tm=label-4;            //处理下边的棋子
            if(tm!=-1&&tm!=-2&&tm!=-3&&tm!=-4)
                temp^=1<<tm;
            tm=label+1;            //处理左边的棋子
            if(tm!=16&&tm!=12&&tm!=8&&tm!=4)
                temp^=1<<tm;
            tm=label-1;            //处理右边的棋子
            if(tm!=11&&tm!=7&&tm!=3&&tm!=-1)
                temp^=1<<tm;
            if(temp==0||temp==65535){
                printf("%d\n",step[t]+1);
                tab=1;
                return;
            }
            if(vis[temp]==0){
                queue[rear++]=temp;
                vis[temp]=1;
                step[temp]=step[t]+1;
            }
        }
    }
}
int main(){
    int i,j;
    char color;
    int id=0;
    for(i=0;i<4;i++)
      for(j=0;j<4;j++)
      {
          cin>>color;
          id<<=1;
          if(color==‘b‘) id+=1;              //计算当前状态

      }
     bfs(id);
     if(tab==0) printf("Impossible");
     return 0;
}
时间: 2024-08-03 23:12:10

poj1753-Flip Game BFS+位运算的相关文章

POJ 1753 bfs+位运算

T_T ++运算符和+1不一样.(i+1)%4 忘带小括号了.bfs函数是bool 型,忘记返回false时的情况了.噢....debug快哭了...... DESCRIPTION:求最少的步骤.使得棋盘上的棋子全黑或者全白.奇数次相当于1次.偶数次相当于不翻. bfs用来求解最优问题.主要用来求距离初始状态路径最短的路径.思想是暴力枚举+位运算.第一次做位运算的题目..醉醉的啦...... 附代码: #include<stdio.h>#include<string.h>#incl

[ACM] POJ 1753 Flip Game (枚举,BFS,位运算)

Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 29921   Accepted: 12975 Description Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the

POJ-1753 Flip Game (BFS+状态压缩)

Description Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the other one is black and each piece is lying either it's black or white side up. Each round you f

POJ 1166 The Clocks 位运算与BFS

1.题意:有一组3*3的只有时针的挂钟阵列,每个时钟只有0,3,6,9三种状态:对时针阵列有9种操作,每种操作只对特点的几个时钟拨一次针,即将时针顺时针波动90度,现在试求从初试状态到阵列全部指向0的状态所需要的最小操作数的操作方案: 2.输入输出:输入给出阵列初始状态,0,1,2,3分别表示0,3,6,9:要求输出最快方案的操作序列: 3.分析:IOI 1994的考题,BFS是比较容易想到的方法之一,关键是如何简洁的表示和改变BFS过程中的阵列状态:这里使用位运算的方法:具体如下: 首先一共9

Vijos 1206 CoVH之再破难关 BFS与位运算

1.题意:一个由01组成的4*4的矩阵,可以实现相邻元素交换位置的操作,给出初试状态和目标状态,试求最少操作数的方案: 2.输入输出:输入给出初试矩阵和目标矩阵:要求输出最小操作的次数: 3.分析:输出最小操作数,很容易联想到使用BFS,这里为了方便表示,把4*4的矩阵拉成一个16个数的数组来看,并用一个16位二进制数表示其状态:用位运算来实现交换某两位的状态,另外再稍微注意一下如何在表示"相邻"的概念即可: 1 # include <iostream> 2 # inclu

【位运算】【BFS】移动玩具

1054: [HAOI2008]移动玩具 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2246  Solved: 1246[Submit][Status][Discuss] Description 在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动 时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩具,请你用最少的移动次数将初始的玩具状态移 动到某人心中的目标状态. Input 前4行表示

FZU1892接水管游戏-BFS加上简单的状态压缩和位运算处理

原题地址:http://acm.fzu.edu.cn/problem.php?pid=1892 Problem 1892 接水管游戏 Accept: 108    Submit: 498 Time Limit: 1000 mSec    Memory Limit : 32768 KB Problem Description 接水管游戏的规则如下: 1.在N*N大小的方格上有两个特别的水管,分别为进水口和出水口: 2.有7种1*1大小的水管需要放在这N*N大小的方格内,使得水流能够从进水口经过这些

bfs+位运算 hdu 5094 有钥匙的迷宫

题意:给你一个n*m的矩阵,每个格子可以移动到他上下左右四个格子.现在有些格子之间有门或墙.墙不能通过,每个门需要对应的钥匙打开.最多10种门,钥匙分布在某些格子上,走到这些格子上就能拿到钥匙.现在要从(1,1)走到(n,m)问最少要走多少步.如果不能到达输出-1. 样例解释: 4 49 9 1 2 1 3 2 1 2 2 2 0 2 1 2 2 0 2 1 3 1 0 2 3 3 3 0 2 4 3 4 1 3 2 3 3 0 3 3 4 3 0 4 3 4 4 0 2 2 1 2 4 2 1

POJ1753——Flip Game

Flip Game Description Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the other one is black and each piece is lying either it's black or white side up. Each r