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

1.题意:一个由01组成的4*4的矩阵,可以实现相邻元素交换位置的操作,给出初试状态和目标状态,试求最少操作数的方案;

2.输入输出:输入给出初试矩阵和目标矩阵;要求输出最小操作的次数;

3.分析:输出最小操作数,很容易联想到使用BFS,这里为了方便表示,把4*4的矩阵拉成一个16个数的数组来看,并用一个16位二进制数表示其状态;用位运算来实现交换某两位的状态,另外再稍微注意一下如何在表示"相邻"的概念即可;

  1 # include <iostream>
  2 # include <cstdio>
  3 # include <queue>
  4 # include <cstring>
  5 using namespace std;
  6 const int MAXN=1<<17;
  7 int vis[MAXN];
  8 int START,END;
  9 int dx[4]={-1,1,4,-4};
 10 void swap(int &a,int &b)
 11 {
 12     int t;
 13     t=a;
 14     a=b;
 15     b=t;
 16 }
 17 struct Node
 18 {
 19     int step,num;
 20     Node(){}
 21     Node(int ss,int nn)
 22     {
 23         step=ss;
 24         num=nn;
 25     }
 26 };
 27 void Init()
 28 {
 29     char M[5][5];
 30     END=START=0;
 31     for(int i=0;i<4;i++)
 32         scanf("%s",M[i]);
 33     for(int i=0;i<4;i++)
 34         for(int j=0;j<4;j++)
 35             START|=((int(M[i][j]-‘0‘))<<(4*i+j));
 36     for(int i=0;i<4;i++)
 37         scanf("%s",M[i]);
 38     for(int i=0;i<4;i++)
 39         for(int j=0;j<4;j++)
 40             END|=((int(M[i][j]-‘0‘))<<(4*i+j));
 41     memset(vis,0,sizeof(vis));
 42 }
 43 int change(int i,int j,int n)
 44 {
 45     int nt=n;
 46     int temp=n;
 47     int subi=(n>>i)&1;//取出i位
 48     int subj=(temp>>j)&1;//取出j位
 49     swap(subi,subj);
 50     nt&=(((1<<16)-1)^(1<<i));
 51     nt&=(((1<<16)-1)^(1<<j));
 52     nt|=(subi<<i);
 53     nt|=(subj<<j);
 54     return nt;
 55 }
 56 void Solve()
 57 {
 58
 59     int ans=-1;
 60     queue<Node> Q;
 61     Q.push(Node(0,START));
 62     while(!Q.empty())
 63     {
 64         Node temp=Q.front();
 65         Q.pop();
 66         if(temp.num==END)
 67         {
 68             ans=temp.step;
 69             break;
 70         }
 71         for(int i=0;i<16;i++)
 72             for(int j=0;j<4;j++)
 73             {
 74                 int t=temp.num;
 75                 if(dx[j]==-1||dx[j]==1)
 76                 {
 77                     if((i/4)==((i+dx[j])/4)&&(i+dx[j])>=0&&(i+dx[j])<16)
 78                     {
 79                         int nt=change(i,i+dx[j],t);
 80                         if(!vis[nt])
 81                         {
 82                             Q.push(Node(temp.step+1,nt));
 83                             vis[nt]=1;
 84                         }
 85                     }
 86                 }
 87                 else
 88                 {
 89                     if((i+dx[j])<16&&(i+dx[j])>=0)
 90                     {
 91                         int nt=change(i,i+dx[j],t);
 92                         if(!vis[nt])
 93                         {
 94                             Q.push(Node(temp.step+1,nt));
 95                             vis[nt]=1;
 96                         }
 97                     }
 98                 }
 99             }
100     }
101     printf("%d\n",ans);
102 }
103 int main()
104 {
105     //freopen("in.txt","r",stdin);
106     //freopen("out.txt","w",stdout);
107     Init();
108     Solve();
109     return 0;
110 } 
时间: 2024-10-31 17:27:20

Vijos 1206 CoVH之再破难关 BFS与位运算的相关文章

Vijos CoVH之再破难关(搜索+hash)

背景 在瞬间之下,明白所有真相只要开始,就不会停止... 揭开唯一事实,外表是小孩,头脑却是大人他的名字就叫...名侦探柯南! 描述 [CoVH07]OIBH组织派出的黄金十二人+青铜五小强还没有到, 他们只能指望原先的机关能够阻拦住柯南的脚步. 柯南打开大门之后发现里面还有一个门, 门上还有一个神奇的锁(-,-) 这是一个4*4的锁, 上面有8个凸起的格子和8个被按下的格子当且仅当两个格子有公共边时, 则称这两个格子是相邻的. 每次操作只能够交换相邻的两个格子 柯南看到了初始锁的状态 和目标锁

黑白棋游戏(或是叫再破难关)——稍微用了下状态压缩的bfs

洛谷和CodeVS 上叫做黑白棋游戏,要求输出路径.CodeVS 上没有spj,洛谷上有但是我的输出总是直接报错.最后找到了Vijos 上的再破难关,一样的题,只是不需要输出路径,交了就对了. 1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<vector> 6 #include<queue> 7 usi

[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

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

【位运算】【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大小的方格内,使得水流能够从进水口经过这些

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

POJ 1753 bfs+位运算

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

[vijos]1051送给圣诞夜的极光&lt;BFS&gt;

送给圣诞夜的极光 题目链接:https://www.vijos.org/p/1051 这是一道很水很水的宽搜水题,我主要是觉得自己在搜素这一块有点生疏于是随便找了一题练手,找到这么一道水题,原本以为可以一次过的,但是状况百出,我并不是很擅长bfs,我以前一直用的Pascal写bfs,但是Pascal没有队列,所以没有c++方便,所以这题我就直接用队列做了,然后完美的炸空间炸时间,后来改成递归调用才通过 思路:这一道题和一道宽搜入门题很像,基本上是一样的,这道题叫细胞个数 链接:http://co