HDOJ-1043 Eight(八数码问题+双向bfs+高效记录路径+康拓展开)

bfs搜索加记录路径

HDOJ-1043

  • 主要思路就是使用双向广度优先搜索,找最短路径。然后记录路径,找到结果是打印出来。
  • 使用康拓序列来来实现状态的映射。
  • 打印路径推荐使用vector最后需要使用algorithm里的reverse进行路径的翻转。
  • 注意本题有多组输入,这里的输入需要注意一下。
  • 如果题目没有要求最短路径,那么使用深搜的话也可以记录路径,这里也给出了代码。
  • 这里的记录路径的方法可以学习。还有判断没有解决方案的解决,利用逆序数。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string>
#include<vector>
#include<map>
using namespace std;
const int maxn=362880;
int state[maxn][9];//从1开始
struct node{
    int x;
    int y;
    int state;//编码
    string s;
};
int fact[9];//阶乘
bool vis[maxn];
bool visr[maxn];
map<int,char> ma;
map<int,char> mar;
void init(){
    fact[0]=1;
    for(int i=1;i<=8;i++){
        fact[i]=fact[i-1]*i;
    }
    ma[0]='u';mar[0]='d';
    ma[1]='l';mar[1]='r';
    ma[2]='d';mar[2]='u';
    ma[3]='r';mar[3]='l';
}
int computeCon(string s){
    int code=0;
    for(int i=0;i<9;i++){
        int cnt=0;
        for(int j=i+1;j<9;j++){
            if(s[j]-'0'<s[i]-'0')
                cnt++;
        }
        code+=fact[8-i]*cnt;
    }
    return code;
}
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
bool in(int x,int y){
    return x>=0&&x<3&&y>=0&&y<3;
}
string path[maxn];//-----------------------这种记录路径的方法很好----------------------------------
void bfs(string s,string final){
    memset(vis,0,sizeof(vis));
    memset(visr,0,sizeof(visr));
    queue<node> q;
    queue<node> q1;
    int sx,sy;
    for(int i=0;i<9;i++){
        if(state[1][i]==0){
            sx=i/3;
            sy=i%3;
            break;
        }
    }
    int con=computeCon(s);
    vis[con]=true;
    node sta=node{sx,sy,con,s};
    q.push(sta);
    int conr=computeCon(final);
    visr[conr]=true;
    q1.push(node{2,2,conr,final});
    path[con]="";
    path[conr]="";
    while(!q.empty()){
        node temp=q.front();
        q.pop();
        //cout<<temp.state<<endl;
        // if(temp.s==final){
        //     //print(temp.state);
        //     cout<<path[temp.state]<<endl;
        //     return true;
        // }
        for(int i=0;i<4;i++){
            int tx=temp.x+dir[i][0];
            int ty=temp.y+dir[i][1];
            int newz=tx*3+ty;
            int oldz=temp.x*3+temp.y;
            if(in(tx,ty)){
                string ns=temp.s;
                ns[newz]=temp.s[oldz];
                ns[oldz]=temp.s[newz];
                int nowcon=computeCon(ns);
                char direction=ma[i];                
                if(visr[nowcon]){
                    reverse(path[nowcon].begin(),path[nowcon].end());
                    cout<<path[temp.state]<<ma[i]<<path[nowcon]<<endl;
                    return;
                }
                if(!vis[nowcon]){
                    vis[nowcon]=1;
                    node now;
                    now.x=tx,now.y=ty,now.s=ns,now.state=nowcon;
                    q.push(now);
                    path[nowcon]=path[temp.state];
                    path[nowcon]+=direction;
                    //path[nowcon]=now;
                    //cout<<now.s<<endl;
                }
            }
        }
        temp=q1.front();
        q1.pop();
        for(int i=0;i<4;i++){
            int tx=temp.x+dir[i][0];
            int ty=temp.y+dir[i][1];
            int newz=tx*3+ty;
            int oldz=temp.x*3+temp.y;
            if(in(tx,ty)){
                string ns=temp.s;
                ns[newz]=temp.s[oldz];
                ns[oldz]=temp.s[newz];
                int nowcon=computeCon(ns);
                char direction=mar[i];                
                if(vis[nowcon]){
                    reverse(path[temp.state].begin(),path[temp.state].end());
                    cout<<path[nowcon]<<mar[i]<<path[temp.state]<<endl;
                    return;
                }
                if(!visr[nowcon]){
                    visr[nowcon]=1;
                    node now;
                    now.x=tx,now.y=ty,now.s=ns,now.state=nowcon;
                    q1.push(now);
                    path[nowcon]=path[temp.state];
                    path[nowcon]+=direction;
                    //path[nowcon]=now;
                    //cout<<now.s<<endl;
                }
            }
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    init();
    char c;
    while(cin>>c){
        string s="";
        if(c=='x')
            state[1][0]=0;
        else state[1][0]=c-'0';
        s+=(state[1][0]+'0');
        for(int i=1;i<=8;i++){
            cin>>c;
            if(c=='x')
                state[1][i]=0;
            else state[1][i]=c-'0';
            s+=(state[1][i]+'0');
        }
        //cout<<s<<endl;
        string final="123456780";
        int k=0;
        for(int i=0;i<9;i++){
            if(!state[1][i])
                continue;
            for(int j=i+1;j<9;j++){
                if(state[1][j]<state[1][i]&&state[1][j]){
                    k++;
                }
            }
        }
        if(k&1){
            cout<<"unsolvable"<<endl;
            continue;    
        }        
        bfs(s,final);
    }
    return 0; 
}

这里是未Ac超时了的代码,而且记录路径的方法没有上面好。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string>
#include<vector>
#include<map>
using namespace std;
const int maxn=362880;
int state[maxn][9];//从1开始
struct node{
    int x;
    int y;
    int state;//编码
    int father;
    char direction;
    string s;
};
int fact[9];//阶乘
bool vis[maxn];
map<int,char> ma;
map<string,int> conma;
void init(){
    fact[0]=1;
    for(int i=1;i<=8;i++){
        fact[i]=fact[i-1]*i;
    }
    ma[0]='u';
    ma[1]='l';
    ma[2]='d';
    ma[3]='r';
}
int computeCon(string s){
    int code=0;
    for(int i=0;i<9;i++){
        int cnt=0;
        for(int j=i+1;j<9;j++){
            if(s[j]-'0'<s[i]-'0')
                cnt++;
        }
        code+=fact[8-i]*cnt;
    }
    return code;
}
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
bool in(int x,int y){
    return x>=0&&x<3&&y>=0&&y<3;
}
node path[maxn];
void print(int state){
    vector<char> v;
    //cout<<state<<endl;
    while(path[state].direction!='n'){
        //cout<<state<<endl;
        v.push_back(path[state].direction);
        state=path[state].father;
    }
    reverse(v.begin(),v.end());
    for(int i=0;i<v.size();i++){
        cout<<v[i];
    }
    cout<<endl;
}
bool bfs(string s,string final){
    memset(vis,0,sizeof(vis));
    queue<node> q;
    int sx,sy;
    for(int i=0;i<9;i++){
        if(state[1][i]==0){
            sx=i/3;
            sy=i%3;
            break;
        }
    }
    int con=computeCon(s);
    vis[con]=true;
    node sta=node{sx,sy,con,-1,'n',s};
    q.push(sta);
    path[con]=sta;
    while(!q.empty()){
        node temp=q.front();
        q.pop();
        //cout<<temp.state<<endl;
        if(temp.s==final){
            print(temp.state);
            return true;
        }
        for(int i=0;i<4;i++){
            int tx=temp.x+dir[i][0];
            int ty=temp.y+dir[i][1];
            int newz=tx*3+ty;
            int oldz=temp.x*3+temp.y;
            if(in(tx,ty)){
                string ns=temp.s;
                ns[newz]=temp.s[oldz];
                ns[oldz]=temp.s[newz];
                int nowcon=computeCon(ns);
                if(!vis[nowcon]){
                    vis[nowcon]=1;
                    node now;
                    char direction=ma[i];
                    now.x=tx,now.y=ty,now.father=temp.state,now.direction=direction,now.s=ns,now.state=nowcon;
                    q.push(now);
                    path[nowcon]=now;
                    //cout<<now.s<<endl;
                }
            }
        }
    }
    return false;
}
int main(){
    init();
    char c;
    while(cin>>c){
        string s="";
        if(c=='x')
            state[1][0]=0;
        else state[1][0]=c-'0';
        s+=(state[1][0]+'0');
        for(int i=1;i<=8;i++){
            cin>>c;
            if(c=='x')
                state[1][i]=0;
            else state[1][i]=c-'0';
            s+=(state[1][i]+'0');
        }
        //cout<<s<<endl;
        string final="123456780";
        if(!bfs(s,final)){
            cout<<"unsolvable"<<endl;
        }
    }
    return 0; 
}
posted @ 2019-08-03 09:53  Garrett_Wale  阅读(120)  评论(0编辑  收藏  举报