HDU1043 Eight(逆向BFS/A*/双向bfs/IDA*)

八数码
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;
}

你可能感兴趣的:(搜索,hdu)