http://acm.hdu.edu.cn/showproblem.php?pid=6171
题目大意:给你一个塔形的数据共有1个0、2个1、3个2、4个3、5个4、6个5.你能够把0这个数据和它的上、左上、下、右下的数据进行交换。问在最多20步内能否变成按顺序排列的塔形数据?如果能输出最小步数,否则输出-1.
解题思路:因为有20步4个方向所以暴力搜索肯定是不可以的。因为有起点有终点所以我们能分两部分去搜索。但是这样搜索的话还是要去找枚举相遇的,这样的话还是会超时的,所以我们在搜索的同时还要找出来一下相遇的最少步数。
我们应该用队列去完成宽搜并用map去存储到达该状态的最少步数,并且起点和终点状态最多只能向前枚举10次以减少时间复杂度。如果在某个状态枚举的情况相遇了则说明已经找到了最少的步数。
我们应该对给出的状态是不是起点状态进行特判,找到最少步数为0的情况。
AC代码:
1 #include <iostream> 2 #include<bits/stdc++.h> 3 //if(~i)//当i不是-1时满足条件 4 using namespace std; 5 queue<string>que; 6 map<string,int>mp; 7 int up[]= {-1,0,-1,1,2,-1,3,4,5,-1,6,7,8,9,-1,10,11,12,13,14,-1}; 8 int upleft[]= {-1,-1,0,-1,1,2,-1,3,4,5,-1,6,7,8,9,-1,10,11,12,13,14}; 9 int down[]= {1,3,4,6,7,8,10,11,12,13,15,16,17,18,19,-1,-1,-1,-1,-1,-1}; 10 int downright[]= {2,4,5,7,8,9,11,12,13,14,16,17,18,19,20,-1,-1,-1,-1,-1,-1}; 11 string ori="011222333344444555555"; 12 13 int solve(string next,string now,int nextpos,int pos) 14 { 15 if(~nextpos) 16 { 17 swap(next[pos],next[nextpos]); 18 next[21]=nextpos/10+'0'; 19 next[22]=nextpos%10+'0'; 20 int cnt1=mp[next]; 21 int cnt2=mp[now]; 22 if(!cnt1) 23 { 24 mp[next]=mp[now]+1; 25 que.push(next); 26 } 27 else if((cnt1>=20&&cnt2<=11)||(cnt2>=20&&cnt1<=11)) 28 return cnt1+cnt2-20; 29 swap(next[pos],next[nextpos]); 30 } 31 return 0; 32 } 33 int dfs(string s) 34 { 35 int index; 36 while(!que.empty()) 37 que.pop(); 38 mp.clear(); 39 for(int i=0; i<21; i++) 40 { 41 if(s[i]=='0') 42 { 43 index=i; 44 break; 45 } 46 } 47 char st[5]; 48 st[0]=index/10+'0'; 49 st[1]=index%10+'0'; 50 st[2]='