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

posted @ 2016-06-21 11:05  FuTaimeng  阅读(295)  评论(0编辑  收藏  举报