题目链接:http://oj.ecustacm.cn/problem.php?id=1318
题目描述
如图所示: 有9只盘子,排成1个圆圈。其中8只盘子内装着8只蚱蜢,有一个是空盘。
我们把这些蚱蜢顺时针编号为 1~8。每只蚱蜢都可以跳到相邻的空盘中,也可以再用点力,越过一个相邻的蚱蜢跳到空盘中。
请你计算一下,如果要使得蚱蜢们的队形改为按照逆时针排列,并且保持空盘的位置不变(也就是1-8换位,2-7换位,...),至少要经过多少次跳跃?

我们把这些蚱蜢顺时针编号为 1~8。每只蚱蜢都可以跳到相邻的空盘中,也可以再用点力,越过一个相邻的蚱蜢跳到空盘中。
请你计算一下,如果要使得蚱蜢们的队形改为按照逆时针排列,并且保持空盘的位置不变(也就是1-8换位,2-7换位,...),至少要经过多少次跳跃?
输出
输出一个整数表示答案
思路:
1、 可以将空盘子看成9的盘子,我们利用状态压缩的思想,把盘子刚开始的状态定义成: 123456789 , 那么最后盘子逆序后的状态就应该为 876543219 ,蚂蚱可以跳一个格子和两个格子,那么蚂蚱的跳跃距离就是|2|距离
2、 我们可以用滚动数组的方法来使盘子可以左右移动 [(x+9)%9]
3、 然后进行广搜就可以了。
#include <iostream> #include <algorithm> #include <string> #include <string.h> #include <vector> #include <map> #include <stack> #include <set> #include <queue> #include <math.h> #include <cstdio> #include <iomanip> #include <time.h> #define LL long long #define INF 0x3f3f3f3f #define ls nod<<1 #define rs (nod<<1)+1 const int maxn = 1e9 + 10 ; const LL mod = 20010905; int st = 123456789,ed = 876543219; int dir[4] = {1,-1,-2,2}; bool vis[maxn]; int a[10]; int getnum() { int sum = 0; for (int i = 0;i < 9;i++) { sum *= 10; sum += a[i]; } return sum; } void bfs() { std::queue<std::pair<int,int> > q; memset(vis,0, sizeof(vis)); q.push(std::make_pair(st,0)); while (!q.empty()) { int x = q.front().first; int step = q.front().second; q.pop(); if (vis[x]) continue; vis[x] = true; if (x == ed) { printf("%d\n",step); return ; } int j = 8,now; while (x) { if (x % 10 == 9) now = j; a[j--] = x % 10; x /= 10; } for (int i = 0;i < 4;i++) { std::swap(a[now],a[(now+dir[i]+9)%9]); int val = getnum(); if (!vis[val]) { q.push(std::make_pair(val,step+1)); } std::swap(a[now],a[(now+dir[i]+9)%9]); } } } int main() { bfs(); return 0; }