题目:
有9只盘子,排成1个圆圈。
其中8只盘子内装着8只蚱蜢,有一个是空盘。
我们把这些蚱蜢顺时针编号为 1~8
每只蚱蜢都可以跳到相邻的空盘中,
也可以再用点力,越过一个相邻的蚱蜢跳到空盘中。
请你计算一下,如果要使得蚱蜢们的队形改为按照逆时针排列,
并且保持空盘的位置不变(也就是1-8换位,2-7换位,…),至少要经过多少次跳跃?
注意:要求提交的是一个整数,请不要填写任何多余内容或说明文字。
思路:bfs + 状态压缩
数字的移动可以看成是空盘的移动,那么空盘的移动方式有四种,向左移动一个,向左移动两个,向右移动一个,向左移动一个。可以用数组 move={-2,-1,1,2} 表示。因为是圆环,所以最后的位置要模 9.
初始状态为123456789, 最终状态为 876543219 . 用 vis 数组来标记改状态是否存在过。
#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
#define Max 1000000000
int vis[Max], a[10];
int s=123456789, t=87654321;
int get_value()
{
int sum = 0;
for(int i=0; i<10; i++)
{
sum *= 10;
sum += a[i];
}
return sum;
}
int bfs()
{
memset(vis,0,sizeof(vis));
Node b;
b.v=s;b.n=0;
queue<Node> q;
a.push(b);
vis[s]=1;
while(!q.empty())
{
Node tmp = q.front();
q.pop();
if(tmp.v == s)
return tmp.n;
int cnt=8,pos;
while(tmp.v)
{
if(tmp.v%10==9) pos=cnt;
a[cnt--] = tmp.v%10;
tmp.v /= 10;
}
for(int i=0; i<4; i++)
{
int k = a[(pos+move[i]+9)%9];
a[(pos+move[i]+9)%9] = a[pos];
a[pos] = k;
int num = get_value();
if(!vis[num])
{
vis[num]=1;
Node c;
c.v=num;c.n=tmp.n+1;
q.push(c);
}
k = a[(pos+move[i]+9)%9];
a[(pos+move[i]+9)%9] = a[pos];
a[pos] = k;
}
}
}
int main()
{
int ans = bfs();
cout<<ans<<endl;
return 0;
}