您的位置:首页 > 其它

POJ 1077 Eight(八数码第四境界|双向广搜+哈希)

2016-01-21 18:46 495 查看
题意:八数码。

思路:这道题用的算法是双向广搜加哈希,因为HDU是多组样例,所以会超时,交的poj。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int MAXN = 400000;
//const int INF = 0x3f3f3f3f;
short int has[MAXN];
int fac[9] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, -1, 0, 1};
int last1[MAXN], last2[MAXN];
short int mov1[MAXN], mov2[MAXN];

struct State {
short int s[9];
short int pos;
int hash;
} ini, target;
queue<State> q1, q2;

int Hash(short int* s) {
int res = 0;
for(int i = 0; i < 8; i++) {
int cnt = 0;
for(int j = i + 1; j < 9; j++) {
if(s[i] > s[j]) cnt++;
}
res += cnt * fac[8-i];
}
return res;
}

int cal_pos(int pos, int i) {
int nx = pos/3+dx[i], ny = pos%3+dy[i];
if(nx<0 || nx>2 || ny<0 || ny>2) return -1;
return nx*3 + ny;
}

void DBFS_init() {
while(!q1.empty()) q1.pop();
while(!q2.empty()) q2.pop();
for(int i = 0; i < 9; i++) target.s[i] = i+1;
target.pos = 8;
target.hash = 0;
has[0] = 2;
q2.push(target);
q1.push(ini);
has[ini.hash] = 1;
}

int q1_expand() {
if(q1.empty()) return -1;
State ha = q1.front();
q1.pop();
State tmp;
for(int i = 0; i < 4; i++) {
tmp.pos = cal_pos(ha.pos, i);
if(tmp.pos<0) continue;
for(int j = 0; j < 9; j++) {
if(j==ha.pos) tmp.s[j] = ha.s[tmp.pos];
else if(j == tmp.pos) tmp.s[j] = ha.s[ha.pos];
else tmp.s[j] = ha.s[j];
}
tmp.hash = Hash(tmp.s);
if(has[tmp.hash] == 1) continue;
q1.push(tmp);
last1[tmp.hash] = ha.hash;
mov1[tmp.hash] = i;
if(has[tmp.hash] == 2) return tmp.hash;
has[tmp.hash] = 1;
}
return -1;
}

int q2_expand() {
if(q2.empty()) return -1;
State ha = q2.front();
q2.pop();
State tmp;
for(int i = 0; i < 4; i++) {
tmp.pos = cal_pos(ha.pos, i);
if(tmp.pos<0) continue;
for(int j = 0; j < 9; j++) {
if(j==ha.pos) tmp.s[j] = ha.s[tmp.pos];
else if(j == tmp.pos) tmp.s[j] = ha.s[ha.pos];
else tmp.s[j] = ha.s[j];
}
tmp.hash = Hash(tmp.s);
if(has[tmp.hash] == 2) continue;
q2.push(tmp);
last2[tmp.hash] = ha.hash;
mov2[tmp.hash] = i;
if(has[tmp.hash] == 1) return tmp.hash;
has[tmp.hash] = 2;
}
return -1;
}

int DBFS() {
DBFS_init();
while(!q1.empty() || !q2.empty()) {
int ans1 = q1_expand();
if(ans1 >= 0) return ans1;
int ans2 = q2_expand();
if(ans2 >= 0) return ans2;
}
return -1;
}

void print_path1(int x) {
if(x==ini.hash) return;
print_path1(last1[x]);
int i = mov1[x];
if(!i) printf("u");
else if(i==1) printf("l");
else if(i==2) printf("d");
else printf("r");

}

void print_path2(int x) {
if(x==0) return;
int i = mov2[x];
if(!i) printf("d");
else if(i==1) printf("r");
else if(i==2) printf("u");
else printf("l");
print_path2(last2[x]);
}

int main() {
//freopen("input.txt", "r", stdin);
char tmp;
while(cin >> tmp) {
memset(has, 0, sizeof(has));
if(tmp != 'x') ini.s[0] = tmp - '0';
else {
ini.s[0] = 9;
ini.pos = 0;
}
for(int i = 1; i < 9; i++) {
cin >> tmp;
if(tmp == 'x') {
ini.s[i] = 9;
ini.pos = i;
}
else ini.s[i] = tmp - '0';
}
ini.hash = Hash(ini.s);
int ans = DBFS();
if(ans < 0) printf("unsolvable");
else {
print_path1(ans);
print_path2(ans);
}
puts("");
}
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息