題目鏈接: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; }
