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