• code1225 八数码Bfs


    Bfs搜索

    1.把棋盘直接作为状态:

    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    using namespace std;
    
    const int n=9;
    const int Size=4;
    int flag;
    struct Point{
        int x,y;
    };
    struct Node{
        int board[Size][Size];
        Point space;
        int step;
    };
    int end[]={0, 1,2,3,8,9,4,7,6,5};
    int dx[4]={-1,0,1,0}; int dy[4]={0,1,0,-1};
    bool visited[400005];
    
    //KT
    int fac[]={1,1,2,6,24,120,720,5040,40320,362880};
    int KT(int s[]){
        int ans=0,smallNum;
        for(int i=1;i<=n;i++){
            smallNum=0;
            for(int j=i+1;j<=n;j++){
                if(s[i]>s[j])smallNum++;
            }
            ans+=smallNum*fac[n-i];
        }
        return ans;
    }
    void InvKT(int k,int s[]){
        int t,j;
        bool v[11]; memset(v,false,sizeof(v));
        for(int i=1;i<=n;i++){
            t=k/fac[n-i];
            for(j=1;j<=n;j++){
                if(v[j]==false){
                    if(t==0)break;
                    else t--;
                }
            }
            s[i]=j; v[j]=true;
            k%=fac[n-i];
        }
    }
    
    //零件
    bool isWin(Node k){
        for(int i=1;i<=3;i++){
            for(int j=1;j<=3;j++){
                if(k.board[i][j]!=end[(i-1)*3+j])return false;
            }
        }
        return true;
    } 
    bool vis(Node k){
        int s[11];
        for(int i=1;i<=3;i++){
            for(int j=1;j<=3;j++){
                s[(i-1)*3+j]=k.board[i][j];
            }
        }
        int num=KT(s);
        if(visited[num]==true)return true;
        else{ visited[num]=true; return false; }
    }
    bool check(Point p){
        if(p.x>=1&&p.y>=1&&p.x<=3&&p.y<=3)return true;
        else return false;
    }
    void swapBoard(Node& k,Point a,Point b){
        int temp=k.board[a.x][a.y];
        k.board[a.x][a.y]=k.board[b.x][b.y];
        k.board[b.x][b.y]=temp;
    }
    void outPut(Node a){
        cout<<"This is a Node:"<<endl;
        for(int i=1;i<=3;i++){
            for(int j=1;j<=3;j++){
                cout<<a.board[i][j]<<' ';
            }
            cout<<endl;
        }
        cout<<"Space: "<<a.space.x<<' '<<a.space.y<<endl;
        cout<<"Step: "<<a.step<<endl;
        
        flag++;
        if(flag>10)exit(0);
    }
    
    //Bfs
    int bfs(Node start){
        memset(visited,false,sizeof(visited));
        queue<Node> q;
        q.push(start);
        vis(start);
        
        while(!q.empty()){
            Node k=q.front(); q.pop();
            //outPut(k);
            for(int i=0;i<4;i++){
                Point newSpace=k.space; newSpace.x+=dx[i]; newSpace.y+=dy[i];
                if(check(newSpace)){
                    Node t=k;
                    swapBoard(t,t.space,newSpace);
                    t.space=newSpace; t.step++;
                    if(isWin(t))return t.step;
                    if(!vis(t))q.push(t);
                }
            }
        }
        return -1;
    }
    
    //Main
    int main(){
        freopen("1225.in","r",stdin);
        
        char cc; Node start;
        for(int i=1;i<=3;i++){
            for(int j=1;j<=3;j++){
                cin>>cc;
                if(cc=='0'){
                    start.board[i][j]=9;
                    start.space.x=i; start.space.y=j;
                }
                else start.board[i][j]=cc-'0';
            }
        } 
        start.step=0;
        cout<<bfs(start)<<endl;
        
        fclose(stdin);
        return 0;
    }

    测试点#1.in 结果: 内存使用量: 488kB 时间使用量: 1ms 
    测试点#2.in 结果: 内存使用量: 1128kB 时间使用量: 3ms 
    测试点#3.in 结果: 内存使用量: 1128kB 时间使用量: 6ms 
    测试点#4.in 结果: 内存使用量: 620kB 时间使用量: 2ms 
    测试点#5.in 结果: 内存使用量: 748kB 时间使用量: 1ms 

    2.把棋盘的康拓作为状态(为A*做准备):

    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    using namespace std;
    
    const int n=9;
    const int Size=4;
    int flag;
    struct Point{
        int x,y;
    };
    int end[]={0, 1,2,3,8,9,4,7,6,5};
    int KTend=-1;
    int dx[4]={-1,0,1,0}; int dy[4]={0,1,0,-1};
    bool visited[400005];
    int f[400005],step[400005],h[400005];
    
    //KT
    int fac[]={1,1,2,6,24,120,720,5040,40320,362880};
    int KT(int s[]){
        int ans=0,smallNum;
        for(int i=1;i<=n;i++){
            smallNum=0;
            for(int j=i+1;j<=n;j++){
                if(s[i]>s[j])smallNum++;
            }
            ans+=smallNum*fac[n-i];
        }
        return ans;
    }
    int KT(int s[Size][Size]){
        int a[11];
        for(int i=1;i<=3;i++){
            for(int j=1;j<=3;j++){
                a[(i-1)*3+j]=s[i][j];
            }
        }
        return KT(a);
    }
    void InvKT(int k,int s[]){
        int t,j;
        bool v[11]; memset(v,false,sizeof(v));
        for(int i=1;i<=n;i++){
            t=k/fac[n-i];
            for(j=1;j<=n;j++){
                if(v[j]==false){
                    if(t==0)break;
                    else t--;
                }
            }
            s[i]=j; v[j]=true;
            k%=fac[n-i];
        }
    }
    void InvKT(int k,int s[Size][Size]){
        int a[11];
        InvKT(k,a);
        for(int i=1;i<=3;i++){
            for(int j=1;j<=3;j++){
                s[i][j]=a[(i-1)*3+j];
            }
        }
    }
    
    //零件
    bool isWin(int kt){
        if(KTend==-1)KTend=KT(end);
        return KTend==kt;
    } 
    bool vis(int kt){
        if(visited[kt]==true)return true;
        else{ visited[kt]=true; return false; }
    }
    bool check(Point p){
        if(p.x>=1&&p.y>=1&&p.x<=3&&p.y<=3)return true;
        else return false;
    }
    void swapBoard(int board[Size][Size],Point a,Point b){
        int temp=board[a.x][a.y];
        board[a.x][a.y]=board[b.x][b.y];
        board[b.x][b.y]=temp;
    }
    Point getSpacePoint(int board[Size][Size]){
        Point p;
        for(int i=1;i<=3;i++){
            for(int j=1;j<=3;j++){
                if(board[i][j]==9){
                    p.x=i; p.y=j;
                    break;
                }
            }
        }
        return p;
    }
    void copy(int a[Size][Size],int b[Size][Size]){
        for(int i=1;i<=3;i++){
            for(int j=1;j<=3;j++){
                b[i][j]=a[i][j];
            }
        }
    }
    
    
    //Bfs
    int bfs(int start){
        memset(visited,false,sizeof(visited));
        queue<int> q;
        q.push(start);
        vis(start);
        step[start]=0;
        
        while(!q.empty()){
            int kt=q.front(); q.pop();
            int s[Size][Size]; InvKT(kt,s);
            Point space=getSpacePoint(s);
            for(int i=0;i<4;i++){
                Point space2=space; space2.x+=dx[i]; space2.y+=dy[i];
                if(check(space2)){
                    int s2[Size][Size]; copy(s,s2);
                    swapBoard(s2,space,space2);
                    int kt2=KT(s2); step[kt2]=step[kt]+1;
                    if(isWin(kt2))return step[kt2];
                    if(!vis(kt2))q.push(kt2);
                }
            }
        }
        return -1;
    }
    
    //Main
    int main(){
        freopen("1225.in","r",stdin);
        
        char cc; int start[11];
        for(int i=1;i<=n;i++){
            cin>>cc;
            if(cc=='0')start[i]=9;
            else start[i]=cc-'0';
        } 
        int KTstart=KT(start);
        cout<<bfs(KTstart)<<endl;
        
        fclose(stdin);
        return 0;
    }
    测试点#1.in  结果:    内存使用量:  620kB     时间使用量:  1ms     
    测试点#2.in 结果: 内存使用量: 2024kB 时间使用量: 8ms
    测试点#3.in 结果: 内存使用量: 2028kB 时间使用量: 6ms
    测试点#4.in 结果: 内存使用量: 1772kB 时间使用量: 2ms
    测试点#5.in 结果: 内存使用量: 1772kB 时间使用量: 3ms

  • 相关阅读:
    第五周
    第四周
    第三周作业
    第二周编程总结
    编程总结(3)
    编程总结(2)
    编程总结(1)
    第七周作业
    第六周作业
    第五周作业
  • 原文地址:https://www.cnblogs.com/FuTaimeng/p/5602957.html
Copyright © 2020-2023  润新知