poj 1077 Eight (BFS)

来源:互联网 发布:淘宝网账号登录历史 编辑:程序博客网 时间:2024/05/24 01:38

八数码问题,各种解法。


/*// BFS#include<iostream>#include<cstdio>#include<queue>using namespace std;// 把1..n的排列映射为数字 0..(n!-1)int fac[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };//...int order(const char *s, int n) {    int i, j, temp, num;    num = 0;    for (i = 0; i < n-1; i++) {        temp = 0;        for (j = i + 1; j < n; j++) {            if (s[j] < s[i])                temp++;        }        num += fac[s[i] -1] * temp;    }    return num;}bool is_equal(const char *b1, const char *b2){    for(int i=0; i<9; i++)        if(b1[i] != b2[i])            return false;    return true;}//hashstruct node{    char board[9];    char space;//空格所在位置};const int TABLE_SIZE = 362880;int hash(const char *cur){    return order(cur, 9);}// 整数映射成排列void get_node(int num, node &tmp) {    int n=9;    int a[9]; //求逆序数    for (int i = 2; i <= n; ++i) {        a[i - 1] = num % i;        num = num / i;        tmp.board[i - 1] = 0;//初始化    }    tmp.board[0] = 0;    int rn, i;    for (int k = n; k >= 2; k--) {        rn = 0;        for (i = n - 1; i >= 0; --i) {            if (tmp.board[i] != 0)                continue;            if (rn == a[k - 1])                break;            ++rn;        }        tmp.board[i] = k;    }    for (i = 0; i < n; ++i)        if (tmp.board[i] == 0) {            tmp.board[i] = 1;            break;        }    tmp.space = n - a[n-1] -1;}char visited[TABLE_SIZE];int parent[TABLE_SIZE];char move[TABLE_SIZE];int step[4][2] = {{-1, 0},{1, 0}, {0, -1}, {0, 1}};//u, d, l, rvoid BFS(const node & start){    int x, y, k, a, b;    int u, v;    for(k=0; k<TABLE_SIZE; ++k)        visited[k] = 0;    u = hash(start.board);    parent[u] = -1;    visited[u] = 1;    queue<int> que;    que.push(u);    node tmp, cur;    while(!que.empty()){        u = que.front();        que.pop();        get_node(u, cur);        k = cur.space;        x = k / 3;        y = k % 3;        for(int i=0; i<4; ++i){            a = x + step[i][0];            b = y + step[i][1];            if(0<=a && a<=2 && 0<=b && b<=2){                tmp = cur;                tmp.space = a*3 + b;                swap(tmp.board[k], tmp.board[tmp.space]);                v = hash(tmp.board);                if(visited[v] != 1){                    move[v] = i;                    visited[v] = 1;                    parent[v] = u;                    if(v == 0) //目标结点hash值为0                        return;                    que.push(v);                }            }        }    }}void print_path(){    int n, u;    char path[1000];    n = 1;    path[0] = move[0];    u = parent[0];    while(parent[u] != -1){        path[n] = move[u];        ++n;        u = parent[u];    }    for(int i=n-1; i>=0; --i){        if(path[i] == 0)            printf("u");        else if(path[i] == 1)            printf("d");        else if(path[i] == 2)            printf("l");        else            printf("r");    }}int main(){//    freopen("in", "r", stdin);    node start;    char c;    for(int i=0; i<9; ++i){        cin>>c;        if(c == 'x'){            start.board[i] = 9;            start.space = i;        }        else            start.board[i] = c - '0';    }    BFS(start);    if(visited[0] == 1)        print_path();    else        printf("unsolvable");    return 0;}// A*#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<queue>using namespace std;// 把1..n的排列映射为数字 0..(n!-1)int fac[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };//...int order(const char *s, int n) {    int i, j, temp, num;    num = 0;    for (i = 0; i < n-1; i++) {        temp = 0;        for (j = i + 1; j < n; j++) {            if (s[j] < s[i])                temp++;        }        num += fac[s[i] -1] * temp;    }    return num;}bool is_equal(const char *b1, const char *b2){    for(int i=0; i<9; i++)        if(b1[i] != b2[i])            return false;    return true;}//hashstruct node{    char board[9];    char space;//空格所在位置};const int TABLE_SIZE = 362880;int hash(const char *cur){    return order(cur, 9);}// 整数映射成排列void get_node(int num, node &tmp) {    int n=9;    int a[9]; //求逆序数    for (int i = 2; i <= n; ++i) {        a[i - 1] = num % i;        num = num / i;        tmp.board[i - 1] = 0;//初始化    }    tmp.board[0] = 0;    int rn, i;    for (int k = n; k >= 2; k--) {        rn = 0;        for (i = n - 1; i >= 0; --i) {            if (tmp.board[i] != 0)                continue;            if (rn == a[k - 1])                break;            ++rn;        }        tmp.board[i] = k;    }    for (i = 0; i < n; ++i)        if (tmp.board[i] == 0) {            tmp.board[i] = 1;            break;        }    tmp.space = n - a[n-1] -1;}//启发函数: 除去x之外到目标的网格距离和int goal_state[9][2] = {{0,0}, {0,1}, {0,2},        {1,0}, {1,1}, {1,2}, {2,0}, {2,1}, {2,2}};int h(const char *board){    int k;    int hv = 0;    for(int i=0; i<3; ++i)        for(int j=0; j<3; ++j){            k = i*3+j;            if(board[k] != 9){                hv += abs(i - goal_state[board[k]-1][0]) +                        abs(j - goal_state[board[k] -1][1]);            }        }    return hv;}int f[TABLE_SIZE], d[TABLE_SIZE];//估计函数和深度//优先队列的比较对象struct cmp{    bool operator () (int u, int v){        return f[u] > f[v];    }};char color[TABLE_SIZE];//0, 未访问;1, 在队列中,2, closedint parent[TABLE_SIZE];char move[TABLE_SIZE];int step[4][2] = {{-1, 0},{1, 0}, {0, -1}, {0, 1}};//u, d, l, rvoid A_star(const node & start){    int x, y, k, a, b;    int u, v;    priority_queue<int, vector<int>, cmp> open;    memset(color, 0, sizeof(char) * TABLE_SIZE);    u = hash(start.board);    parent[u] = -1;    d[u] = 0;    f[u] = h(start.board);    open.push(u);    color[u] = 1;    node tmp, cur;    while(!open.empty()){        u = open.top();        if(u == 0)            return;        open.pop();        get_node(u, cur);        k = cur.space;        x = k / 3;        y = k % 3;        for(int i=0; i<4; ++i){            a = x + step[i][0];            b = y + step[i][1];            if(0<=a && a<=2 && 0<=b && b<=2){                tmp = cur;                tmp.space = a*3 + b;                swap(tmp.board[k], tmp.board[tmp.space]);                v = hash(tmp.board);                if(color[v] == 1 && (d[u] + 1) < d[v]){//v in open                    move[v] = i;                    f[v] = f[v] - d[v] + d[u] + 1;//h[v]已经求过                    d[v] = d[u] + 1;                    parent[v] = u;                    //直接插入新值, 有冗余,但不会错                    open.push(v);                }                else if(color[v] == 2 && (d[u]+1)<d[v]){//v in closed                    move[v] = i;                    f[v] = f[v] - d[v] + d[u] + 1;//h[v]已经求过                    d[v] = d[u] + 1;                    parent[v] = u;                    open.push(v);                    color[v] = 1;                }                else if(color[v] == 0){                    move[v] = i;                    d[v] = d[u] + 1;                    f[v] = d[v] + h(tmp.board);                    parent[v] = u;                    open.push(v);                    color[v] = 1;                }            }        }        color[u] = 2; //    }}void print_path(){    int n, u;    char path[1000];    n = 1;    path[0] = move[0];    u = parent[0];    while(parent[u] != -1){        path[n] = move[u];        ++n;        u = parent[u];    }    for(int i=n-1; i>=0; --i){        if(path[i] == 0)            printf("u");        else if(path[i] == 1)            printf("d");        else if(path[i] == 2)            printf("l");        else            printf("r");    }}int main(){    //freopen("in", "r", stdin);    node start;    char c;    for(int i=0; i<9; ++i){        cin>>c;        if(c == 'x'){            start.board[i] = 9;            start.space = i;        }        else            start.board[i] = c - '0';    }    A_star(start);    if(color[0] != 0)        print_path();    else        printf("unsolvable");    return 0;}// IDA*#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;#define    SIZE 3char board[SIZE][SIZE];//启发函数: 除去x之外到目标的网格距离和int goal_state[9][2] = {{0,0}, {0,1}, {0,2},        {1,0}, {1,1}, {1,2}, {2,0}, {2,1}, {2,2}};int h(char board[][SIZE]){    int cost = 0;    for(int i=0; i<SIZE; ++i)        for(int j=0; j<SIZE; ++j){            if(board[i][j] != SIZE*SIZE){                cost += abs(i - goal_state[board[i][j]-1][0]) +                        abs(j - goal_state[board[i][j]-1][1]);            }        }    return cost;}int step[4][2] = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};//u, l, r, dchar op[4] = {'u', 'l', 'r', 'd'};char solution[1000];int bound;     //上界bool ans;    //是否找到答案int DFS(int x, int y, int dv, char pre_move){// 返回next_bound    int hv = h(board);    if(hv + dv > bound)        return dv + hv;    if(hv == 0){        ans = true;        return dv;    }    int next_bound = 1e9;    for(int i=0; i<4; ++i){        if(i + pre_move == 3)//与上一步相反的移动            continue;        int nx = x + step[i][0];        int ny = y + step[i][1];        if(0<=nx && nx<SIZE && 0<=ny && ny<SIZE){            solution[dv] = i;            swap(board[x][y], board[nx][ny]);            int new_bound = DFS(nx, ny, dv+1, i);            if(ans)                return new_bound;            next_bound = min(next_bound, new_bound);            swap(board[x][y], board[nx][ny]);        }    }    return next_bound;}void IDA_star(int sx, int sy){    ans = false;    bound = h(board);//初始代价    while(!ans && bound <= 100)//上限        bound = DFS(sx, sy, 0, -10);}int main(){    freopen("in", "r", stdin);    int sx, sy;//起始位置    char c;    for(int i=0; i<SIZE; ++i)        for(int j=0; j<SIZE; ++j){            cin>>c;            if(c == 'x'){                board[i][j] = SIZE * SIZE;                sx = i;                sy = j;            }            else                board[i][j] = c - '0';        }    IDA_star(sx, sy);    if(ans){        for(int i=0; i<bound; ++i)            cout<<op[solution[i]];    }    else        cout<<"unsolvable";    return 0;}*/#include<stdio.h>#include<queue>#include<string.h>#include<iostream>#include<algorithm>using namespace std;const int MAXN=1000000;int fac[]={1,1,2,6,24,120,720,5040,40320,362880};//康拖展开判重//         0!1!2!3! 4! 5!  6!  7!   8!    9!bool vis[MAXN];//标记int cantor(int s[])//康拖展开求该序列的hash值{    int sum=0;    for(int i=0;i<9;i++)    {        int num=0;        for(int j=i+1;j<9;j++)          if(s[j]<s[i])num++;        sum+=(num*fac[9-i-1]);    }    return sum+1;}struct Node{    int s[9];    int loc;//“0”的位置,把“x"当0    int status;//康拖展开的hash值    string path;//路径};string path;int aim=46234;//123456780对应的康拖展开的hash值int move[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//u,d,l,rchar indexs[5]="udlr";//正向搜索Node ncur;bool bfs(){    memset(vis,false,sizeof(vis));    Node cur,next;    queue<Node>q;    q.push(ncur);    while(!q.empty())    {        cur=q.front();        q.pop();        if(cur.status==aim)        {            path=cur.path;            return true;        }        int x=cur.loc/3;        int y=cur.loc%3;        for(int i=0;i<4;i++)        {            int tx=x+move[i][0];            int ty=y+move[i][1];            if(tx<0||tx>2||ty<0||ty>2)continue;            next=cur;            next.loc=tx*3+ty;            next.s[cur.loc]=next.s[next.loc];            next.s[next.loc]=0;            next.status=cantor(next.s);            if(!vis[next.status])            {                vis[next.status]=true;                next.path=next.path+indexs[i];                if(next.status==aim)                {                    path=next.path;                    return true;                }                q.push(next);            }        }    }    return false;}int main(){    char ch;    while(cin>>ch)    {        if(ch=='x') {ncur.s[0]=0;ncur.loc=0;}        else ncur.s[0]=ch-'0';        for(int i=1;i<9;i++)        {            cin>>ch;            if(ch=='x')            {                ncur.s[i]=0;                ncur.loc=i;            }            else ncur.s[i]=ch-'0';        }        ncur.status=cantor(ncur.s);        if(bfs())        {            cout<<path<<endl;        }        else cout<<"unsolvable"<<endl;    }    return 0;}


0 0
原创粉丝点击