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 结果:AC 内存使用量: 488kB 时间使用量: 1ms 
测试点#2.in 结果:AC 内存使用量: 1128kB 时间使用量: 3ms 
测试点#3.in 结果:AC 内存使用量: 1128kB 时间使用量: 6ms 
测试点#4.in 结果:AC 内存使用量: 620kB 时间使用量: 2ms 
测试点#5.in 结果:AC 内存使用量: 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  结果:AC    内存使用量:  620kB     时间使用量:  1ms     测试点#2.in  结果:AC    内存使用量:  2024kB     时间使用量:  8ms     测试点#3.in  结果:AC    内存使用量:  2028kB     时间使用量:  6ms     测试点#4.in  结果:AC    内存使用量:  1772kB     时间使用量:  2ms     测试点#5.in  结果:AC    内存使用量:  1772kB     时间使用量:  3ms
时间: 2024-08-30 10:05:05

code1225 八数码Bfs的相关文章

poj 1077 八数码(BFS+康托展开)

1 /* 2 题意:八数码问题,给出3*3的矩阵含1~8以及x,给出一个符合的解使得移动后的矩阵的顺序为1~8,最后为x 3 4 题解:BFS 5 需要用到康托展开来表示状态,不然数组无法完全表示所有状态,这样BFS就无法判断找不到解的情况(status 6 的0ms,0KB究竟是怎么做到的,简直不能想象=.=) 7 */ 8 #include <cstdio> 9 #include <cstring> 10 #include <queue> 11 #include &

HDU1043 八数码(BFS + 打表)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 , 康托展开 + BFS + 打表. 经典八数码问题,传说此题不做人生不完整,关于八数码的八境界:http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html 我自己是用哈希(康托展开) + BFS  + 打表过的,第三重境界. 由于一些高级的搜索现在还没学,所以目前能升级的也就是用双向BFS来做了,等过几天有心情了来做. 本文

luogu_1379 八数码难题

八数码-->BFS+set 1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 #include<set> 6 using namespace std; 7 struct aaa{ 8 int map[4][4]; 9 int dep,x,y; 10 }que[370000]; 11 set<int> ssr; 12

HDU 1043 Eight八数码解题思路(bfs+hash 打表 IDA* 等)

题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原为初始状态 思路: 参加网站比赛时拿到此题目,因为之前写过八数码问题,心中暗喜,于是写出一套暴力bfs+hash,结果TLE呵呵 思路一:bfs+hash(TLE) 1 #include <cstdio> 2 #include <cstring> 3 #include <queu

cdoj 1380 Xiper的奇妙历险(2) [八数码问题 bfs + 预处理]

快要NOIP 2016 了,现在已经停课集训了.计划用10天来复习以前学习过的所有内容.首先就是搜索. 八数码是一道很经典的搜索题,普通的bfs就可求出.为了优化效率,我曾经用过康托展开来优化空间,甚至还用过A*来优化时间.不过这道题懒得写了,就一个普普通通的bfs,再加上一个stl 的map就水过了. 首先题目要求有多达10000组数据,依次搜索肯定是不行的,我试过用A*来写,第2组数据就会T掉,所以我们考虑用一个预处理.从末尾状态搜索所有可行的状态,并用一个map来存储答案.然后就很好写了.

BFS(八数码) POJ 1077 || HDOJ 1043 Eight

题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状态逆向搜索,这样才不会超时.判重康托展开,哈希也可. POJ //#include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<string> #include<stack

八数码问题+路径寻找问题+bfs(隐式图的判重操作)

Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 process()  初始化vis数组,初始化初始节点到目标节点的移动距离 dfs()搜索到每一个节点,如果不是目标节点,对其依次扩展所有子节点,并判重,全部子节点搜索完全后,改变父节点:如果是目标节点成功返回 输出最少移动步数 input: 2 6 4 1 3 7 0 5 8 8 1 5 7 3 6

【算法】BFS+哈希解决八数码问题

15拼图已经有超过100年; 即使你不叫这个名字知道的话,你已经看到了.它被构造成具有15滑动砖,每一个从1到15上,并且所有包装成4乘4帧与一个瓦块丢失.让我们把丢失的瓷砖"X"; 拼图的目的是安排瓷砖以便它们排序为: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15× 这里唯一合法经营是交流'X'与它共享一个边缘的瓷砖之一.作为一个例子,举动下列顺序解决了一个稍微加扰难题: 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 7 8 5 6

UVALive 6665 Dragon&#226;??s Cruller --BFS,类八数码问题

题意大概就是八数码问题,只不过把空格的移动方式改变了:空格能够向前或向后移动一格或三格(循环的). 分析:其实跟八数码问题差不多,用康托展开记录状态,bfs即可. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue&g