poj 1043

来源:互联网 发布:mp3剪辑合并软件 编辑:程序博客网 时间:2024/05/29 17:21

poj 1043


经典的八数码问题,这个问题最重要的是hash函数的使用,用来判重,因为是记录路径,所以用bfs最好了


#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#define M 362888using namespace std;int map[12];  bool vis[M];struct NODE{    long long num,pre,dir;}Q[M<<3];int dt[4][2]={{1,0},{0,1},{-1,0},{0,-1}};const int fact[9] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};long long step[M];long long canto(){        int j, i, tmp;        long long ans;        for (ans = 1, i = 0; i < 9; i++)        {                for (tmp = map[i] - 1, j = 0; j < i; j++)                        tmp -= (map[j] < map[i]);                ans = ans + tmp * fact[8 - i];        }        return ans;}void antihash(long long num){    int k=8;    while(k!=-1)    {        map[k--]=num%10;        num=num/10;    }}long long hash(){    long long num=0;    for(int i=0;i<=8;i++)        num=num*10+map[i];    return num;}long long bfs(){    int head=1,tail=2;    long long sp=hash();    Q[1].num=sp; Q[1].dir=-1; Q[1].pre=-1;    long long val=canto(); vis[val]=true;    while(head<tail)    {        int pos;        NODE sta=Q[head];        antihash(sta.num); val=canto();        if(val==1) return(head);//stop        for(int i=0;i<9;i++)//find pos           if(map[i]==9) {pos=i;i=100;}        int x=pos%3,y=pos/3;//pos        for(int i=0;i<4;i++)        {            int nx=x,ny=y;            nx+=dt[i][0];            ny+=dt[i][1];            if(ny>=0&&ny<3&&nx>=0&&nx<3)            {                int pos1=x+y*3;//last pos                int pos2=nx+ny*3;//new pos                swap(map[pos1],map[pos2]);                val=canto();                if(!vis[val])                {                    vis[val]=true;                    NODE dick;                    dick.num=hash(); dick.pre=head; dick.dir=i;                    Q[tail++]=dick;                }                swap(map[pos1],map[pos2]);            }        }        head++;    }    return -1;}void print(int hd){    int wx=0;    while(Q[hd].pre!=-1)    {        step[++wx]=Q[hd].dir;        hd=Q[hd].pre;    }    for(int i=wx;i>=1;i--)    {        if(step[i]==0) printf("r");        else if(step[i]==1) printf("d");        else if(step[i]==2) printf("l");        else if(step[i]==3) printf("u");    }}void solve(){    int hd=bfs();    if(hd==-1) printf("unsolvable");    else print(hd);}int main(){    char a;    for(int i=0;i<9;i++)    {        cin>>a;        if(a=='x') map[i]=9;        else map[i]=a-'0';    }    solve();    //system("pause");    return 0;}

因为hash函数我并不是很理解,所以改成set,就TLE了,看来stl有时候还是谨慎使用呀

#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <set>#define M 362888using namespace std;int map[12];  bool vis[M];struct NODE{    long long num,pre,dir;}Q[M<<3];set<int> st;int dt[4][2]={{1,0},{0,1},{-1,0},{0,-1}};//const int fact[9] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};long long step[M];/*long long canto(){        int j, i, tmp;        long long ans;        for (ans = 1, i = 0; i < 9; i++)        {                for (tmp = map[i] - 1, j = 0; j < i; j++)                        tmp -= (map[j] < map[i]);                ans = ans + tmp * fact[8 - i];        }        return ans;}*/void antihash(long long num){    int k=8;    while(k!=-1)    {        map[k--]=num%10;        num=num/10;    }}long long hash(){    long long num=0;    for(int i=0;i<=8;i++)        num=num*10+map[i];    return num;}long long bfs(){    int head=1,tail=2;    st.clear();    long long sp=hash();    //cout<<sp<<endl;    Q[1].num=sp; Q[1].dir=-1; Q[1].pre=-1;    st.insert(sp);    while(head<tail)    {        int pos;        NODE sta=Q[head];        if(sta.num==123456789) return head;        antihash(sta.num);        for(int i=0;i<9;i++)//find pos           if(map[i]==9) {pos=i;i=100;}        int x=pos%3,y=pos/3;//pos        for(int i=0;i<4;i++)        {            int nx=x,ny=y;            nx+=dt[i][0];            ny+=dt[i][1];            if(ny>=0&&ny<3&&nx>=0&&nx<3)            {                int pos1=x+y*3;//last pos                int pos2=nx+ny*3;//new pos                swap(map[pos1],map[pos2]);                int val=hash();                                if(st.find(val)==st.end())                {                    st.insert(val);                    NODE dick;                    dick.num=val;                    dick.pre=head;                    dick.dir=i;                    Q[tail++]=dick;                }                swap(map[pos1],map[pos2]);            }        }        head++;    }    return -1;}void print(int hd){    int wx=0;    while(Q[hd].pre!=-1)    {        step[++wx]=Q[hd].dir;        hd=Q[hd].pre;    }    for(int i=wx;i>=1;i--)    {        if(step[i]==0) printf("r");        else if(step[i]==1) printf("d");        else if(step[i]==2) printf("l");        else if(step[i]==3) printf("u");    }}void solve(){    int hd=bfs();    if(hd==-1) printf("unsolvable");    else print(hd);}int main(){    char a;    for(int i=0;i<9;i++)    {        cin>>a;        if(a=='x') map[i]=9;        else map[i]=a-'0';    }    solve();    //system("pause");    return 0;}


原创粉丝点击