HDU 1043——八數碼的多種解題思路(持續更新)
八數碼算是一個比較經典的搜尋問題了。
hdu 1043: http://acm.hdu.edu.cn/showproblem.php?pid=1043
poj 1077: http://poj.org/problem?id=1077
1.樸素廣搜+雜湊:
#include <cstdio>
#include <string>
#include <queue>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
struct Node {
int s[9];
int loc;
int status;
};
queue<Node> q;
struct Path {
int fa;
char d;
};
Path path[500000];
string s,_ans;
int a[10],F[10];
int jud[500000];
int dir_jud[4][9] = {
//rlud
1,1,0,1,1,0,1,1,0,
0,1,1,0,1,1,0,1,1,
0,0,0,1,1,1,1,1,1,
1,1,1,1,1,1,0,0,0
};
int dir[4] ={1,-1,-3,3};
char zifu[10] = {"rlud"};
int Cantor(int a[]) {
int ans = 0;
for (int i = 0; i < 9; i++) {
int t = 0;
for (int j = 0; j < i; j++) {
if(a[j]<a[i]) t++;
}
ans+=(a[i]-t-1)*F[9-i-1];
}
return ans;
}
void read(){
int j = 0;
for (int i = 0; i < s.size(); i++) {
if(s[i]>='1'&&s[i]<='9') {
a[j++] = s[i]-'0';
}
else if(s[i]=='x') {
a[j++] = 9;
}
}
}
int check(int a[]) {
int ans = 0;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < i; j++) {
if(a[i]<a[j]&&a[j]!=9) ans++;
}
}
return ans;
}
void cal(){
F[0] = 1;
for (int i = 1; i <= 9; i++)
F[i] = i*F[i-1];
}
int bfs(){
while(!q.empty()){
if (!q.front().status) return 1;
for (int i = 0; i < 4; i++) {
Node tt = q.front();
if (dir_jud[i][tt.loc]) {
swap(tt.s[tt.loc],tt.s[tt.loc+dir[i]]);
tt.status = Cantor(tt.s);
if (!jud[tt.status]) {
jud[tt.status] = 1;
path[tt.status].fa = q.front().status;
path[tt.status].d = zifu[i];
tt.loc += dir[i];
q.push(tt);
}
}
}
q.pop();
}
return 0;
}
int main(){
while(getline(cin,s)){
q = queue<Node> ();
memset(path,0,sizeof(path));
memset(jud,0,sizeof(jud));
read();cal();
if(check(a)%2) {
puts("unsolvable");
continue;
}
Node start;
for(int i = 0; i < 9; i++) {
start.s[i] = a[i];
if(a[i]==9)start.loc = i;
}
start.status = Cantor(start.s);
q.push(start);
path[start.status].fa = -1;
jud[start.status] = 1;
if(!bfs()) {
puts("unsolvable");
continue;
}
int i = 0;
while (path[i].fa!=-1) {
_ans.push_back(path[i].d);
i = path[i].fa;
}
reverse(_ans.begin(),_ans.end());
cout << _ans << endl;
}
return 0;
}
2.廣搜打表+雜湊#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define MAXN 362880
using namespace std;
int a[10];
char s[1000];
int F[10];
struct Node{
int s[9];
int zero;
int status;
};
queue<Node> q;
struct Path{
int fa;
char d;
};
Path path[MAXN];
bool jud[MAXN];
//rlud
char z[10] = {"lrdu"};
int dir[4] = {1,-1,-3,3};
bool pre_d[4][9] = {
1,1,0,1,1,0,1,1,0,
0,1,1,0,1,1,0,1,1,
0,0,0,1,1,1,1,1,1,
1,1,1,1,1,1,0,0,0
};
int Cantor(int c[]) {
int ans = 0;
for (int i = 0;i < 9; i++) {
int t = 0;
for (int j = 0; j < i; j++) {
if (c[j]<c[i]) t++;
}
ans+=F[9-i-1]*(c[i]-t-1);
}
return ans;
}
void bfs() {
while (!q.empty()) {
for (int i = 0; i < 4; i++) {
Node t = q.front();
if(pre_d[i][t.zero]==1) {
swap(t.s[t.zero], t.s[t.zero+dir[i]]);
t.status = Cantor(t.s);
if(jud[t.status]==0) {
jud[t.status] = 1;
t.zero += dir[i];
path[t.status].fa = q.front().status;
path[t.status].d = z[i];
q.push(t);
}
}
}
q.pop();
}
}
int main() {
F[0] = 1;
for (int i = 1; i < 9; i++) F[i] = F[i-1]*i;
Node start;
for (int i = 0; i < 9; i++) start.s[i] = i+1;
start.zero = 8;
start.status = 0;
jud[0] = 1;
path[0].fa = -1;
q.push(start);
bfs();
while(cin.getline(s,1000)){
int j = 0;
for (int i = 0; i < strlen(s); i++) {
if(s[i]<='9'&&s[i]>='1') a[j++] = s[i]-'0';
else if (s[i]=='x') a[j++] = 9;
}
int ans = Cantor(a);
if(jud[ans]==0) {
puts("unsolvable");
}
else{
while(path[ans].fa!=-1) {
printf("%c",path[ans].d);
ans=path[ans].fa;
}
printf("\n");
}
}
return 0;
}
3.雙向廣搜
// #include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <queue>
using namespace std;
char s[1000];
string ANS[2];
int f[10];
int a[10];
char z[2][10] = {"lrud","rldu"};
int dir[4] = {1,-1,3,-3};
int p_dir[4][9] = {
1,1,0,1,1,0,1,1,0,
0,1,1,0,1,1,0,1,1,
1,1,1,1,1,1,0,0,0,
0,0,0,1,1,1,1,1,1
};
struct Node {
int zero, status;
int s[9];
Node(){};
Node(int Z,int S){
zero = Z, status = S;
}
};
struct Path {
int fa; char c;
Path(){};
Path(int FA,int C) {
fa = FA, c = C;
}
};
Path path[400000];
queue<Node> q[2];
int jud[400000];
int Cantor(int a[]) {
int ans = 0;
for (int i = 0; i < 9; i++) {
int t = 0;
for (int j = 0; j < i; j++)
if (a[i]>a[j]) t++;
ans+=f[9-i-1]*(a[i]-1-t);
}
return ans;
}
int ca;
void dbfs(){
while (!q[0].empty()&&!q[1].empty()) {
for (int j = 0; j < 2; j++) {
for (int i = 0; i < 4; i++) {
if (p_dir[i][q[j].front().zero]) {
Node t = q[j].front();
swap(t.s[t.zero],t.s[t.zero+dir[i]]);
t.status = Cantor(t.s);
if (!jud[t.status]) {
path[t.status].fa = q[j].front().status;
path[t.status].c = z[j][i];
jud[t.status] = j+1;
t.zero += dir[i];
q[j].push(t);
}
else{
if (jud[t.status]==2-j) {
int t1 = q[j].front().status;
int t2 = t.status;
ANS[j]+=z[j][i];
while (path[t1].fa!=-1) {
ANS[j]+=path[t1].c;
t1 = path[t1].fa;
}
while (path[t2].fa!=-1) {
ANS[1-j]+=path[t2].c;
t2 = path[t2].fa;
}
reverse(ANS[1].begin(),ANS[1].end());
cout << ANS[1]<<ANS[0]<<endl;
return;
}
}
}
}
q[j].pop();
}
}
puts("unsolvable");
}
int check(int a[]) {
int ans = 0;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < i; j++) {
if(a[i]<a[j]&&a[j]!=9) ans++;
}
}
return ans;
}
int main() {
f[0] = 1;
for (int i = 1; i < 10; i++) f[i] = f[i-1]*i;
while(cin.getline(s, 1000)) {
memset(path,0,sizeof(path));
memset(jud,0,sizeof(jud));
q[0] = q[1] = queue<Node>();
ANS[0].clear();ANS[1].clear();
int j = 0, t = 0;
for (int i = 0; i < strlen(s); ++i) {
if (s[i]<='8'&&s[i]>='1') {
a[j++] = s[i]-'0';
}
else if (s[i]=='x'){
a[j++] = 9;
t = j-1;
}
}
if(check(a)%2) {
puts("unsolvable");
continue;
}
int ans = Cantor(a);
q[1].push(Node(t,ans));
q[0].push(Node(8,0));
for (int i = 0 ; i < 9; i++) {
q[0].front().s[i] = i+1;
q[1].front().s[i] = a[i];
}
path[0].fa = path[ans].fa= -1;
jud[0] = 1;
jud[ans] = 2;
dbfs();
}
return 0;
}
注:這題資料好像挺水的,poj無unslovable資料,另外以提交結果看,雙向廣搜並不快(才不是寫的蠢)
相關文章
- leetcode題解【持續更新】LeetCode
- AI面試題(持續更新)AI面試題
- Hbase面試題(持續更新)面試題
- mdk的命令講解(持續更新)
- Flutter 問題集,持續更新Flutter
- 前端程式碼集合(持續更新)前端
- 各種命令,以及FAQ..持續更新.....
- Spring面試題(持續更新中)Spring面試題
- 前端面試問題(持續更新)前端面試
- javaScript 習題總結(持續更新)JavaScript
- 常用程式碼筆記-持續更新筆記
- 上下文詳解(持續更新)
- JVM(持續更新。。。)JVM
- FastApi持續更新ASTAPI
- 跨域資源共享的各種方式(持續更新)跨域
- thymeleaf的坑(持續更新。。。)
- 前端面試問題二(持續更新)前端面試
- PHP面試題總結-持續更新中PHP面試題
- GO面試題集錦快答[持續更新]Go面試題
- ASP.net常用程式碼(持續更新)ASP.NET
- [持續更新]hive異常解決方案Hive
- LeetCode Animation 題目圖解彙總(持續更新中...)LeetCode圖解
- Blender 雕刻 持續更新
- 有用的網站(持續更新)網站
- 資料分析面試|SQL真題持續更新面試SQL
- hadoop 日常問題彙總(持續更新)Hadoop
- 【CTF入門】BUUCTF Misc刷題(持續更新)
- java程式碼編寫優化(持續更新...)Java優化
- git 遇到的錯誤以及解決方式(持續更新...)Git
- LeetCode All in One 題目講解彙總(持續更新中...)LeetCode
- LeetCode刷題:數學篇(C++實現,持續更新中...)LeetCodeC++
- MySql報錯(持續更新)MySql
- Pycharm快捷鍵持續更新PyCharm
- Xcode 技巧 持續更新XCode
- git使用、持續更新中Git
- 踩坑記[持續更新]
- litepal筆記(持續更新)筆記
- leetcode(持續更新......)LeetCode