资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
123.46758
样例输出
3
样例输入
13524678.
46758123.
46758123.
样例输出
22
这题与状态和步数相关,首先就是想到搜索,要得到从初态到终态所需最少步数→广搜,一旦出现终态那就是最少步数.
第一遍写的时候没有记录出现过的局面进行剪枝,于是超时了,后来用map记录出现过的局面,每个局面都用一个字符串表示,重复出现的局面就不再入队了,这样修改之后再提交就能过了.
不过这种方法并不是很好,耗时长,占内存大(375ms | 21.98MB),搜了一些别人的代码提交了一下,都比这种方法更优(15ms | 13.77MB,125ms | 10.83MB),不过对我来说这种方法比较好理解,也容易想到,总之思路没歪就好.
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <string> 6 #include <cmath> 7 #include <map> 8 #include <queue> 9 #include <algorithm> 10 #define INF 0x3f3f3f3f 11 #define zero 1e-7 12 13 using namespace std; 14 typedef long long ll; 15 const ll mod=1e9+7; 16 const ll max_n=5e5+7; 17 //9*8*7*6*5*4*3*2*1=362880 18 struct node { 19 string s;//当前局面 20 int p;//该局面空格所在位置 21 int step;//到达当前局面经过了多少步 22 }; 23 queue<node> q; 24 map<string, int> mp;//记录出现过的局面 25 26 string s1, s2;//初态,终态 27 28 void add(node t, int p) {//当前局面,新局面中空格所在位置 29 string ss=t.s; 30 ss[t.p]=ss[p]; 31 ss[p]='.'; 32 if(mp.find(ss)==mp.end()) {//若局面ss未曾出现过 33 mp[ss]=1;//记录该局面 34 node temp={ss, p, t.step+1}; 35 q.push(temp);//将该局面相关信息入队 36 } 37 } 38 //广搜 39 int bfs() { 40 while(!q.empty()) { 41 node t=q.front(); 42 q.pop(); 43 if(t.s==s2) {//一旦该局面与目标局面一致,其步数即最少所需步数 44 return t.step; 45 } 46 int pp; 47 string ss; 48 if(t.p/3>0) //空格不在第一行,可与它上方那格数字交换 49 add(t, t.p-3); 50 if(t.p/3<2) //空格不在第三行,可与它下方那格数字交换 51 add(t, t.p+3); 52 if(t.p%3>0) //空格不在第一列,可与它左边那格数字交换 53 add(t, t.p-1); 54 if(t.p%3<2) //空格不在第三列,可与它右边那格数字交换 55 add(t, t.p+1); 56 } 57 return -1;//若无法达到目标局面,则返回-1 58 } 59 60 int main() { 61 int p; 62 mp.clear(); 63 while(!q.empty()) q.pop();//队列清空 64 cin>>s1>>s2; 65 for(int i=0; i<9; i++) { 66 if(s1[i]=='.') { 67 p=i; 68 break; 69 } 70 } 71 node temp={s1, p, 0};//当前局面,空格的位置,步数 72 q.push(temp); 73 mp[temp.s]=1; 74 int mint=bfs(); 75 cout<<mint<<endl; 76 return 0; 77 }