1. 程式人生 > >九宮重排(搜索)

九宮重排(搜索)

star 技術 輸出格式 一行 tmp end memcmp text 重復

1581: 題目名稱:九宮重排

時間限制: 1 Sec 內存限制: 128 MB
提交: 2 解決: 1
[提交] [狀態] [討論版] [命題人:外部導入]

題目描述

問題描述
如下面第一個圖的九宮格中,放著 1~8 的數字卡片,還有一個格子空著。與空格子相鄰的格子中的卡片可以移動到空格中。經過若幹次移動,可以形成第二個圖所示的局面。
我們把第一個圖的局面記為:12345678.
把第二個圖的局面記為:123.46758技術分享圖片
顯然是按從上到下,從左到右的順序記錄數字,空格記為句點。
本題目的任務是已知九宮的初態和終態,求最少經過多少步的移動可以到達。如果無論多少步都無法到達,則輸出-1。

輸入

輸入格式
輸入第一行包含九宮的初態,第二行包含九宮的終態。

輸出

輸出格式
輸出最少的步數,如果不存在方案,則輸出-1。

樣例輸入

12345678.
123.46758

樣例輸出

3
bfs+康托展開判斷是否重復操作
#include<bits/stdc++.h>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
int p[15], q[15],t[1000005][15
],cnt[1000005],vis[1000005]; int fac[15] = { 1 }; int d[5][5] = { {1,0},{-1,0},{0,1},{0,-1} }; int kt(int *a) { int sum = 0,u=0; for (int i = 0; i < 8; i++) { u = 0; for (int j = i + 1; j < 9; j++) { if (a[i] > a[j])u++; } sum += u * fac[8
- i]; } if (vis[sum])return 0; else { vis[sum] = 1; return 1; } } int bfs() { int head = 0, tail = 1; memcpy(t[0], p, sizeof(p)); while (head < tail) { int tmp[15]; memcpy(tmp, t[head], sizeof(t[head])); if (memcmp(tmp, q,sizeof(q)) == 0)return head; int k; for (k = 0; k < 9; k++)if (!tmp[k])break; int x = k / 3, y = k % 3; for (int i = 0; i < 4; i++) { int cx = x + d[i][0], cy = y+d[i][1]; if (cx < 0 || cy < 0 || cx>2 || cy>2)continue; int now = 3 * cx + cy; int temp[15]; memcpy(temp, tmp, sizeof(tmp)); temp[k] = tmp[now]; temp[now] = 0; if (kt(temp))memcpy(t[tail],temp,sizeof(temp)),cnt[tail++] = cnt[head]+1; } ++head; } return -1; } int main() { char ch; //for (int i = 1; i <= 10; i++)cout << fac[i] << endl; for (int i = 1; i <= 9; i++)fac[i] = i * fac[i - 1]; //for (int i = 1; i <= 10; i++)cout << fac[i] << endl; for (int i = 0; i < 9; i++) { cin >> ch; if (ch == .)p[i] = 0; else p[i] = ch - 0; } for (int i = 0; i < 9; i++) { cin >> ch; if (ch == .)q[i] = 0; else q[i] = ch - 0; } int ans = bfs(); if (ans == -1)cout << -1 << endl; else cout << cnt[ans] << endl; return 0; }

九宮重排(搜索)