题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567
主要练习双BFS的写法。只有一个注意点,见代码。手写了一个模拟队列,可惜时间根本没有提升,不知为啥,在HDU上提交时,得选C++,G++会TLE。
代码:
#include<iostream>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<string>
#define LL __int64
#define INF 0x7fffffff
using namespace std;
struct node{
int s[9],n,cur,step;
}o,st,ed;
int fac[]={1,1,2,6,24,120,720,5040,40320};
int cantor(int *s){//康托展开
int sum=0;
for(int i=0;i<9;i++){
int cnt=0;
for(int j=i+1;j<9;j++)
if(s[i]<s[j]) cnt++;
sum+=(fac[9-i-1]*cnt);
}
return sum;
}
int d[][2]={1,0,0,-1,0,1,-1,0};
string dir="dlru";
int vis[2][363010];
string ans[363010];//存储路径,其实可以每个点只存储一个字符,但是没写出来,放弃了
void bfs(){
memset(vis,0,sizeof(vis));
for(int i=0;i<363000;i++) ans[i].clear();
queue<node> Q[2];
Q[0].push(st);Q[1].push(ed);
vis[0][st.n]=vis[1][ed.n]=1;
int deep=0;
while(!Q[0].empty() || Q[1].empty()){
int i=0;
while(i<2){
node tp=Q[i].front();
if(tp.step!=deep) {i++;continue;}
Q[i].pop();
int x=tp.cur/3,y=tp.cur%3;
for(int p=0;p<4;p++){
int tx=x+d[p][0],ty=y+d[p][1];
if(tx<0 || ty<0 || tx>=3 || ty>=3) continue;
node tp2=tp;tp2.cur=tx*3+ty;tp2.step=tp.step+1;
swap(tp2.s[tp.cur],tp2.s[tp2.cur]);
tp2.n=cantor(tp2.s);
if(!i && vis[1][tp2.n]){//为了保证最小字典序,只能i为0是才能输出
ans[tp.n]+=dir[p];
reverse(ans[tp2.n].begin(),ans[tp2.n].end());
cout<<(int)ans[tp.n].size()+(int)ans[tp2.n].size()<<endl;
cout<<ans[tp.n]<<ans[tp2.n]<<endl;return;
}
int k=i? 3-p:p;
if(vis[1-i][tp2.n]) continue;
if(!i && vis[i][tp2.n]) continue;
//主要注意点就是下面这个if,对于反向搜索,需要判断新方向是否可以改变最小字典序
if(i && vis[i][tp2.n] && ans[tp2.n][(int)ans[tp2.n].size()-1]<dir[k]) continue;
ans[tp2.n]=ans[tp.n];ans[tp2.n]+=dir[k];
Q[i].push(tp2);vis[i][tp2.n]=1;
}
}
deep++;
}
}
int main(){
//freopen("D:\\in.txt","r",stdin);
//freopen("D:\\out.txt","w",stdout);
int T;cin>>T;
for(int kase=1;kase<=T;kase++){
char ch;
for(int i=0;i<9;i++){
cin>>ch;if(ch=='X') ch='0',st.cur=i;
st.s[i]=ch-'0';
}
for(int i=0;i<9;i++){
cin>>ch;if(ch=='X') ch='0',ed.cur=i;
ed.s[i]=ch-'0';
}
st.step=ed.step=0;
st.n=cantor(st.s);ed.n=(cantor(ed.s));
printf("Case %d: ",kase);
if(st.n==ed.n){cout<<0<<endl<<endl;continue;}
bfs();
}
return 0;
}