【Codevs1225】 八数码难题 BFS (1/1000)

来源:互联网 发布:道路照度计算软件 编辑:程序博客网 时间:2024/05/19 11:46

很经典的一道题,我用的是宽度优先搜索,set判重,本来这题可以用康托展开和逆展开,再开一个大数组,判重可做到O(1)的时间复杂度,这里偷一个懒,直接将数组变成了一个9位数,统统丢set去判重,set查找效率还是很高的,毕竟红黑树,这里还顺便复习了一下结构体的初始化,每个结构体都代表一个状态,每个状态储存着一个9位数,步数,空格位置,似乎每一个都是必须。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<queue>#include<set>using namespace std;struct state{    int num;    int step;    int pos;};queue<state> Q;set<int> S;char ch;int space,sum,goal=123804765;int d[4]={-1,1,-3,3},num[9];int code(){    int t=0;    for(int i=0;i<9;i++){        t=10*t+num[i];    }    return t;}int decode(int n){    for(int i=8;i>=0;i--){        num[i]=n%10;        n/=10;    }}int main(){    //freopen("in.txt","r",stdin);     //freopen("out.txt","w",stdout);     for(int i=0;i<9;i++){        cin>>ch;        num[i]=ch-'0';        if (num[i]==0) space=i;    }    state first={code(),0,space};    Q.push(first);    while(!Q.empty()){        state tmp=Q.front();Q.pop();        decode(tmp.num);        for(int i=0;i<4;i++){            if ((i==0)&&(tmp.pos==0||tmp.pos==3||tmp.pos==6)) continue;            if ((i==1)&&(tmp.pos==2||tmp.pos==5||tmp.pos==8)) continue;            if ((i==2)&&(tmp.pos==0||tmp.pos==1||tmp.pos==2)) continue;            if ((i==3)&&(tmp.pos==6||tmp.pos==7||tmp.pos==8)) continue;            swap(num[tmp.pos+d[i]],num[tmp.pos]);            sum=code();            if (sum==goal){                cout<<tmp.step+1<<endl;                return 0;            }            if (S.find(sum)==S.end()){                S.insert(sum);                 state tmp1={sum,tmp.step+1,tmp.pos+d[i]};                Q.push(tmp1);            }            swap(num[tmp.pos+d[i]],num[tmp.pos]);        }       }    return 0;}

这题还可以用A*来做,留个坑,下次填上