【Aizu - 0121】Seven Puzzle (反向bfs)
阿新 • • 發佈:2019-07-15
-->Seven Puzzle
原文是日語 這裡就直接寫中文了
Descriptions:
7拼圖由8個正方形的卡和這些卡片完全收納的框構成。每張卡都編號為0, 1, 2, …, 7,以便相互區別。框架中,可以縱向排列2張,橫向排列4張卡。
7當拼圖開始時,首先把所有的卡放入框架。在框架中只有0的卡可以與上下左右相鄰的卡交換位置。例如,當框架的狀態為圖A時,與0卡的右邊相鄰的、7的卡交換位置,就變成圖B的狀態。或者,從圖(a)的狀態與0卡下面鄰接的2卡交換位置的話,成為圖c的狀態。在圖(a)的狀態下0卡與上下左右相鄰的卡只有7 2卡,此外的位置不允許更換。
遊戲的目的是將卡片排列整齊,使圖形(d)的狀態。請建立一個程式,輸入第一個狀態,直到卡片排列整齊為止,輸出必要的最小麻煩。但是,輸入了的卡的狀態可以轉移到圖d的狀態。
輸入資料以空白分隔符給出1行中的8個數字。這些表示第一狀態的卡片排列。例如,圖(a)的數字表示為0 7 3 4 2 5 6,圖(c)為2 7 3 4 0 5 1 6。
input
以上格式提供多個謎題。請處理到輸入的最後。給定的謎題的數量在1,000以下。
output
請將每個拼圖輸出到最後一行的最小麻煩。
Sample Input
0 1 2 3 4 5 6 7
1 0 2 3 4 5 6 7
7 6 5 4 3 2 1 0
Output for the Sample Input
0
1
28
題目連結:
https://vjudge.net/problem/Aizu-0121
從目標卡牌序列"01234567"開始著手入佇列,然後走出不同的卡牌序列,再將走出這些卡牌序列的步數儲存,最後比對題目要求的卡牌序列,找出答案即可,程式碼有詳解
AC程式碼:
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #include <sstream> #define mod 1000000007 #define eps 1e-6 #define ll long long #define INF 0x3f3f3f3f #define MEM(x,y) memset(x,y,sizeof(x)) #define Maxn 310 using namespace std; map<string,int>mp;//卡牌序列對應的步數 queue<string>q;//卡牌序列 string now,net; string s; //移動方向,右,左,上,下(給定一維陣列,要向上(下),就是往前(後)推四張牌) int dt[]= {1,-1,4,-4}; void bfs() { q.push("01234567"); while(!q.empty()) { now=q.front(); q.pop(); int pos=now.find('0');//找到0的位置 for(int i=0; i<4; i++) { int tpos=pos+dt[i]; //3、7位置不能往右移 0、4位置不能往左移 if(tpos>=0&&tpos<8&&(!((pos==3||pos==7)&&i==0)&&!((pos==0||pos==4)&&i==1))) { net=now; swap(net[pos],net[tpos]);//交換pos和tpos位置的數字,形成新的卡牌序列 if(mp[net]==0)//卡牌序列沒出現過 { mp[net]=mp[now]+1;//步數+1 q.push(net); } } } } return; } int main() { bfs();//初始化,找出所有可能的卡牌序列 mp["01234567"] = 0; while(1) { s="";//存放題目要求的卡牌序列 int a = 8,b; while(a--) { if(!(cin >> b)) return 0;//這一行的處理是加了個結尾,不加的話死迴圈 s += b+'/0'; } cout <<mp[s] << endl; } return 0; }
&n