蒟蒻目前还不会什么高端的算法,只能暴力一点写BFS。
不过也是刚刚了解到双向BFS,就拿这道比较简单的题来练练手,第一次写双向BFS。
http://blog.sina.com.cn/s/blog_6635898a0100p4wd.html
这篇博客介绍得还是蛮清楚的,本身也不复杂,就是从初态开始BFS寻找末态的同时也从末态开始BFS寻找初态。搜索树一有交叉就可以得到一条完整的初态到末态的路径。比普通的BFS要快很多,大概要降一个根号级别。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#define M 362900
typedef long long L;
using namespace std;
int beg, end = 46234, fa[M], nx[M], e[9], fac[10] = {1};
char r1[M], r2[M];
bool vis1[M], vis2[M];
queue <int> q1, q2;
int get(){
char c = getchar();
while((c < '0' || c > '9') && c != 'x') c = getchar();
if(c == 'x') return 0;
return c-'0';
}
int cot(int *a){
int res = 0;
bool vis[10];
memset(vis, 0, sizeof vis);
for(int i = 0; i < 9; i++){
int k = 0;
vis[a[i]] = 1;
for(int j = 0; j < a[i]; j++){
k += !vis[j];
}
res += k*fac[8-i];
}
return res+1;
}
void nicot(int x){
x--;
int k[10];
for(int i = 8; i; i--){
k[i] = x/fac[i];
x %= fac[i];
}
bool vis[10];
memset(vis, 0, sizeof vis);
for(int i = 1; i < 9; i++){
int n = k[9-i]+1, l = 0;
for(int j = 0; j < 9; j++){
l += !vis[j];
if(l == n){
vis[j] = 1;
e[i-1] = j;
break;
}
}
}
for(int i = 0; i < 9; i++){
if(vis[i]) continue;
e[8] = i;
break;
}
}
void print(int mid){
stack <char> s;
int k = mid, j, posj, posk;
while(fa[k]){
j = fa[k];
nicot(j);
for(int i = 0; i < 9; i++){
if(!e[i]) posj = i;
}
nicot(k);
for(int i = 0; i < 9; i++){
if(!e[i]) posk = i;
}
if(posk == posj + 1) s.push('r');
if(posk == posj - 1) s.push('l');
if(posk == posj + 3) s.push('d');
if(posk == posj - 3) s.push('u');
k = j;
}
while(!s.empty()){
printf("%c", s.top());
s.pop();
}
j = mid;
while(nx[j]){
k = nx[j];
nicot(j);
for(int i = 0; i < 9; i++){
if(!e[i]) posj = i;
}
nicot(k);
for(int i = 0; i < 9; i++){
if(!e[i]) posk = i;
}
if(posk == posj + 1) putchar('r');
if(posk == posj - 1) putchar('l');
if(posk == posj + 3) putchar('d');
if(posk == posj - 3) putchar('u');
j = k;
}
}
int main()
{
for(int i = 0; i < 9; i++){
e[i] = get();
fac[i+1] = fac[i]*(i+1);
}
beg = cot(e);
if(beg == end){
return 0;
}
vis1[beg] = 1;
vis2[end] = 1;
q1.push(beg);
q2.push(end);
while(!q1.empty() || !q2.empty()){
if(!q1.empty()){
int k = q1.front();
q1.pop();
nicot(k);
int pos;
for(int i = 0; i < 9; i++){
if(!e[i]) pos = i;
}
if(pos % 3){
swap(e[pos], e[pos-1]);
int j = cot(e);
if(!vis1[j]){
vis1[j] = 1;
q1.push(j);
fa[j] = k;
}
if(vis2[j]){
print(j);
return 0;
}
swap(e[pos], e[pos-1]);
}
if(pos > 3){
swap(e[pos], e[pos-3]);
int j = cot(e);
if(!vis1[j]){
vis1[j] = 1;
q1.push(j);
fa[j] = k;
}
if(vis2[j]){
print(j);
return 0;
}
swap(e[pos], e[pos-3]);
}
if(pos % 3 != 2){
swap(e[pos], e[pos+1]);
int j = cot(e);
if(!vis1[j]){
vis1[j] = 1;
q1.push(j);
fa[j] = k;
}
if(vis2[j]){
print(j);
return 0;
}
swap(e[pos], e[pos+1]);
}
if(pos < 6){
swap(e[pos], e[pos+3]);
int j = cot(e);
if(!vis1[j]){
vis1[j] = 1;
q1.push(j);
fa[j] = k;
}
if(vis2[j]){
print(j);
return 0;
}
swap(e[pos], e[pos+3]);
}
}
if(!q2.empty()){
int k = q2.front();
q2.pop();
nicot(k);
int pos;
for(int i = 0; i < 9; i++){
if(!e[i]) pos = i;
}
if(pos > 3){
swap(e[pos], e[pos-3]);
int j = cot(e);
if(!vis2[j]){
vis2[j] = 1;
q2.push(j);
nx[j] = k;
}
if(vis1[j]){
print(j);
return 0;
}
swap(e[pos], e[pos-3]);
}
if(pos % 3){
swap(e[pos], e[pos-1]);
int j = cot(e);
if(!vis2[j]){
vis2[j] = 1;
q2.push(j);
nx[j] = k;
}
if(vis1[j]){
print(j);
return 0;
}
swap(e[pos], e[pos-1]);
}
if(pos % 3 != 2){
swap(e[pos], e[pos+1]);
int j = cot(e);
if(!vis2[j]){
vis2[j] = 1;
q2.push(j);
nx[j] = k;
}
if(vis1[j]){
print(j);
return 0;
}
swap(e[pos], e[pos+1]);
}
if(pos < 6){
swap(e[pos], e[pos+3]);
int j = cot(e);
if(!vis2[j]){
vis2[j] = 1;
q2.push(j);
nx[j] = k;
}
if(vis1[j]){
print(j);
return 0;
}
swap(e[pos], e[pos+3]);
}
}
}
printf("unsolvable");
return 0;
}
这次也是神奇,除了一开始没看清末态WA了一次,一遍就AC。
感觉以自己的码力这题要调老长时间。或许是本来就好写,细节少 →.→ ,好大一部分都是复制粘贴的。