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

Posted cn_XuYang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 } 

 

以上是关于Vijos 1206 CoVH之再破难关 BFS与位运算的主要内容,如果未能解决你的问题,请参考以下文章

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

Vijos CoVH之柯南开锁 (二分图)

vijos p1204——CoVH之柯南开锁

vijos1026 BFS与位运算

Vijos1605 NOIP2008 提高组T4 双栈排序 BFS

Vijos P1360 八数码问题