八数码
cantor 展开:一个全排列的rank,用来hash
逆向bfs:62msAC
#include
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
const LL mod=1e9+7;
const double eps=1e-9;
string Input;
char str[10];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
char predir[5]="udlr";
int nxt[500000];
int op[500000];
int is[500000];
struct node{
char mp[10];
int x,y;
};
int cantor(char *s){
int ans=0;
for(int i=0;i<8;++i){
for(int j=i+1;j<9;++j)if(s[j]<s[i])ans++;
ans*=(8-i);
}
return ans;
}
int trans(int x,int y){
return 3*(x-1)+y-1;
}
void bfs(){
node st;
for(int i=0;i<9;i++){st.mp[i]=i;}
st.x=3,st.y=3;
int sthsh=cantor(st.mp);
is[sthsh]=1;nxt[sthsh]=-1;
queue<node>mq;
mq.push(st);
while(!mq.empty()){
node nw=mq.front();
mq.pop();int prehsh=cantor(nw.mp);
for(int i=0;i<4;i++){
node pp=nw;
int nxtx=pp.x+dx[i];
int nxty=pp.y+dy[i];
if(nxtx<1||nxtx>3||nxty<1||nxty>3)continue;
swap(pp.mp[trans(pp.x,pp.y)],pp.mp[trans(nxtx,nxty)]);
int hsh=cantor(pp.mp);
if(is[hsh])continue;
pp.x=nxtx,pp.y=nxty;op[hsh]=i;nxt[hsh]=prehsh;
is[hsh]=1;
mq.push(pp);
}
}
}
void print(int q){
if(!q){cout<<endl;return ;}
cout<<predir[op[q]];
print(nxt[q]);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
bfs();
while(getline(cin,Input)){
int k=0;
for(int i=0;i<Input.length();i++){
if(Input[i]=='x'){
Input[i]='9';
}
if(Input[i]==' ')continue;
str[k++]=Input[i];
}
int hsh=cantor(str);
if(is[hsh])print(hsh);
else cout<<"unsolvable"<<endl;
}
return 0;
}
A* 655ms
估价函数是除了*以外,其他数归位的曼哈顿距离和
#include
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
const LL mod=1e9+7;
const double eps=1e-9;
string Input;
char str[10];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
char nxtdir[5]="durl";
char predir[5]="udlr";
int nxt[500000];
int pre[500000];
int op[500000];
int is[500000];
struct node{
char mp[10];
int x,y;
int g,h;
bool operator <(const node &a)const{
return g+h>a.g+a.h;
}
};
int cantor(char *s){
int ans=0;
for(int i=0;i<8;++i){
for(int j=i+1;j<9;++j)if(s[j]<s[i])ans++;
ans*=(8-i);
}
return ans;
}
int solvable(char *s){
int cnt=0;
for(int i=0;i<8;i++){
if(s[i]==9)continue;
for(int j=i+1;j<9;j++){
if(s[j]==9)continue;
if(s[i]>s[j])cnt++;
}
}
return !(cnt&1);
}
int trans(int x,int y){
return 3*(x-1)+y-1;
}
int get_h(char *s){
int h=0;
for(int i=0;i<9;i++){
if(s[i]!=9)h+=(abs(i/3-(s[i]-1)/3)+abs(i%3-(s[i]-1)%3));
}
return h;
}
priority_queue<node>mq;
void Astar(node st,node ed){
memset(is,0,sizeof is);
while(!mq.empty())mq.pop();
int sths=cantor(st.mp);
int edhs=cantor(ed.mp);
is[sths]=1;op[sths]=-1;st.g=0;
mq.push(st);
while(!mq.empty()){
node nw=mq.top();
mq.pop();
int nwhs=cantor(nw.mp);
if(nwhs==edhs)break;
for(int i=0;i<4;i++){
node pp=nw;
int nxtx=nw.x+dx[i];
int nxty=nw.y+dy[i];
if(nxtx>3||nxtx<1||nxty>3||nxty<1)continue;
swap(pp.mp[trans(pp.x,pp.y)],pp.mp[trans(nxtx,nxty)]);
pp.x=nxtx;
pp.y=nxty;
int pphs=cantor(pp.mp);
if(is[pphs])continue;
pp.g++;op[pphs]=i;nxt[pphs]=nwhs;
pp.h=get_h(pp.mp);
is[pphs]=1;
mq.push(pp);
}
}
}
void print(int q,int sthsh){
if(q==sthsh){return ;}
print(nxt[q],sthsh);
cout<<nxtdir[op[q]];
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
node ed;
for(int i=0;i<9;i++)ed.mp[i]=i+1;
while(getline(cin,Input)){
int k=0;
node st;
for(int i=0;i<Input.length();i++){
if(Input[i]=='x'){
Input[i]='9';
st.x=k/3+1;
st.y=k%3+1;
}
if(Input[i]==' ')continue;
st.mp[k++]=Input[i]-'0';
}
if(solvable(st.mp)){
Astar(st,ed);
print(cantor(ed.mp),cantor(st.mp));
cout<<endl;
}
else cout<<"unsolvable"<<endl;
}
return 0;
}
双向bfs 670ms
#include
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
const LL mod=1e9+7;
const double eps=1e-9;
string Input;
char str[10];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
char nxtdir[5]="durl";
char predir[5]="udlr";
int nxt[2][500000];
int op[2][500000];
int is[500000];
struct node{
char mp[10];
int x,y;
int d,hsh;
};
int cantor(char *s){
int ans=0;
for(int i=0;i<8;++i){
for(int j=i+1;j<9;++j)if(s[j]<s[i])ans++;
ans*=(8-i);
}
return ans;
}
int solvable(char *s){
int cnt=0;
for(int i=0;i<8;i++){
if(s[i]==9)continue;
for(int j=i+1;j<9;j++){
if(s[j]==9)continue;
if(s[i]>s[j])cnt++;
}
}
return !(cnt&1);
}
int trans(int x,int y){
return 3*(x-1)+y-1;
}
void printpre(int q,int sthsh){
if(q==sthsh){return ;}
printpre(nxt[0][q],sthsh);
cout<<nxtdir[op[0][q]];
}
void printnxt(int q,int edhsh){
if(q==edhsh){return ;}
cout<<predir[op[1][q]];
printnxt(nxt[1][q],edhsh);
}
void bibfs(node st,node ed){
memset(is,-1,sizeof is);
queue<node>mq[2];
st.d=0;ed.d=0;
st.hsh=cantor(st.mp);
ed.hsh=cantor(ed.mp);
is[st.hsh]=0,is[ed.hsh]=1;
mq[0].push(st);
mq[1].push(ed);
int opq;
while(!mq[0].empty()||!mq[1].empty()){
if(mq[0].size()<mq[1].size())opq=0;
else opq=1;
node tmp=mq[opq].front();
while(!mq[opq].empty()){
if(mq[opq].front().d!=tmp.d)break;
node nw=mq[opq].front();mq[opq].pop();
for(int i=0;i<4;i++){
node pp=nw;
int nxtx=pp.x+dx[i];
int nxty=pp.y+dy[i];
if(nxtx<1||nxtx>3||nxty<1||nxty>3)continue;
swap(pp.mp[trans(nxtx,nxty)],pp.mp[trans(pp.x,pp.y)]);
pp.x=nxtx;
pp.y=nxty;
pp.d=nw.d+1;
pp.hsh=cantor(pp.mp);
if(is[pp.hsh]==opq){continue;}
else {
nxt[opq][pp.hsh]=nw.hsh;
op[opq][pp.hsh]=i;
if(is[pp.hsh]==(opq^1)){
printpre(pp.hsh,st.hsh);
printnxt(pp.hsh,ed.hsh);
return ;
}
mq[opq].push(pp);
is[pp.hsh]=opq;
}
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
node ed;
for(int i=0;i<9;i++)ed.mp[i]=i+1;
ed.x=3,ed.y=3;
while(getline(cin,Input)){
int k=0;
node st;
for(int i=0;i<Input.length();i++){
if(Input[i]=='x'){
Input[i]='9';
st.x=k/3+1;
st.y=k%3+1;
}
if(Input[i]==' ')continue;
st.mp[k++]=Input[i]-'0';
}
if(solvable(st.mp)){
bibfs(st,ed);
cout<<endl;
}
else cout<<"unsolvable"<<endl;
}
return 0;
}
IDA* 702ms 可能写的太搓了。。。初始化有点花时间
#include
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
const LL mod=1e9+7;
const double eps=1e-9;
string Input;
char str[10];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
int is[500000];
char nxtdir[5]="durl";
char predir[5]="udlr";
stack<char>ans;
struct node{
char mp[10];
int x,y,h,hsh;
}st;
int cantor(char *s){
int ans=0;
for(int i=0;i<8;++i){
for(int j=i+1;j<9;++j)if(s[j]<s[i])ans++;
ans*=(8-i);
}
return ans;
}
int solvable(char *s){
int cnt=0;
for(int i=0;i<8;i++){
if(s[i]==9)continue;
for(int j=i+1;j<9;j++){
if(s[j]==9)continue;
if(s[i]>s[j])cnt++;
}
}
return !(cnt&1);
}
inline int trans(int x,int y){return 3*(x-1)+y-1;}
int get_h(char *s){
int h=0;
for(int i=0;i<9;i++)if(s[i]!=9)h+=(abs(i/3-(s[i]-1)/3)+abs(i%3-(s[i]-1)%3));
return h;
}
int debug(){
for(int i=0;i<9;i++)cout<<(int)st.mp[i];
cout<<' '<<st.h<<endl;
}
int IDA(int mxd,int d){
//debug();
if(!st.h)return 1;
if(d+st.h>mxd||is[st.hsh]<d)return 0;
is[st.hsh]=d;
node tmp=st;
for(int i=0;i<4;i++){
st.x=tmp.x+dx[i];
st.y=tmp.y+dy[i];
if(st.x>3||st.x<1||st.y<1||st.y>3){st=tmp;continue;}
swap(st.mp[trans(st.x,st.y)],st.mp[trans(tmp.x,tmp.y)]);
st.hsh=cantor(st.mp);
st.h=get_h(st.mp);
if(IDA(mxd,d+1)){ans.push(nxtdir[i]);return 1;}
st=tmp;
}
//debug();
return 0;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while(getline(cin,Input)){
int k=0;
for(int i=0;i<Input.length();i++){
if(Input[i]=='x'){
Input[i]='9';
st.x=k/3+1;
st.y=k%3+1;
}
if(Input[i]==' ')continue;
st.mp[k++]=Input[i]-'0';
}
st.h=get_h(st.mp);
st.hsh=cantor(st.mp);
if(solvable(st.mp)){
memset(is,INF,sizeof is);
for(int i=st.h;!IDA(i,0);i++){}
while(!ans.empty()){cout<<ans.top();ans.pop();}
cout<<endl;
}
else cout<<"unsolvable"<<endl;
}
return 0;
}