hdu 1043(经典搜索)

来源:互联网 发布:数据库系统及其应用 编辑:程序博客网 时间:2024/05/22 13:05

题意:

给你一个初始的图,然后每次输入一个图,要求移动x最小的步数达到和初始图一样,输出路径

1  2  3  4     1  2  3  4     1  2  3  4     1  2  3  4 5  6  7  8     5  6  7  8     5  6  7  8     5  6  7  8 9  x 10 12     9 10  x 12     9 10 11 12     9 10 11 1213 14 11 15    13 14 11 15    13 14  x 15    13 14 15  x            r->            d->            r->

好像有很多中方法解决这个问题:八数码的八个境界

①bfs + 康托展开+打表         /* 其他的还不会,有空去试试 - -

#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <cstdlib>#include <queue>#include <algorithm>typedef long long ll;using namespace std;const int MAXN=362900;//最多是9!/2int fac[]= {1,1,2,6,24,120,720,5040,40320,362880}; //康拖展开判重//         0!1!2!3! 4! 5!  6!  7!   8!    9!bool vis[MAXN];//标记char path[MAXN][40];//记录路径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 matri[10];    int position;    char path[50];    int state;};queue<node>que;char dire[5] = "dlur";int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};void bfs(){    memset(vis,false,sizeof(vis));    node cur;    for(int i = 0; i < 8; i++)        cur.matri[i] = i+1;    cur.matri[8] = 0;    cur.state = 46234;    cur.path[0] = '\0';    cur.position = 8;    que.push(cur);    vis[cur.state] = true;    path[cur.state][0] = '\0';    while(!que.empty())    {        cur = que.front();        que.pop();        int x = cur.position/3;        int y = cur.position%3;        for(int i = 0; i < 4; i++)        {            int tx = x + dir[i][0];            int ty = y + dir[i][1];            if(tx < 0 || tx > 2 || ty < 0 || ty > 2)                continue;            node t = cur;            t.position =tx*3+ty;            t.matri[cur.position] = t.matri[t.position];            t.matri[t.position] = 0;            t.state =cantor(t.matri);            if(!vis[t.state])            {                path[t.state][0] = t.path[0] = dire[i];                int len = strlen(cur.path);                for(int j = 1;j <= len+1;j++)                    path[t.state][j] = t.path[j] = cur.path[j-1];                vis[t.state] = true;                que.push(t);            }        }    }}char ch;int q[10];int main(){    bfs();    while(cin >> ch)    {        if(ch == 'x')            q[0] = 0;        else            q[0] = ch-'0';        for(int i = 1; i < 9; i++)        {            cin >> ch;            if(ch == 'x')                q[i] = 0;            else                q[i] = ch-'0';        }        int ans = cantor(q);       // printf("%d\n",ans);        if(!vis[ans])            printf("unsolvable\n");        else        {            cout <<path[ans]<<endl;        }    }    return 0;}


②双向bfs + 康拓展开+奇偶剪枝

剪枝:当x左右移动时,序列不变;上下移动时,移动2位后逆序数+2,所以奇偶性不变

双向bfs:因为扩展越大,你要搜索的部分就更多.而同时从开头和结果开始理论上来说会快很多

#include <iostream>#include <cstdio>#include <cstring>#include <ctime>#include <algorithm>#include <cmath>#include <queue>#include <map>#include <vector>typedef long long ll;using namespace std;const int MAXN=370000;int fac[]= {1,1,2,6,24,120,720,5040,40320,362880}; //康拖展开判重//         0!1!2!3! 4! 5!  6!  7!   8!    9!int  vis[MAXN];//标记int  vis2[MAXN];int cantor(string 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{    string path;    int state;} From;struct node2{    int num;    char ch;} pre[MAXN];char dire2[5] = "dlur";char dire1[5] = "urdl";int dir[4] = {-3,1,3,-1};void pri(int t){    if(pre[t].num == -1)        return ;    pri(pre[t].num);    printf("%c",pre[t].ch);}void bfs(node cur){    queue<node>que1;    queue<node>que2;    memset(vis,0,sizeof(vis));    memset(vis2,0,sizeof(vis2));    pre[0].num = pre[1].num  = pre[2].num = -1;    node last,tp;    vis[cantor(cur.path)] = 1;    last.path ="123456780";    last.state = 8;    vis2[cantor(last.path)] = 2;    que1.push(From);    que2.push(last);    int num = 2;    while(!que1.empty() && !que2.empty())    {        //正向搜索        cur = que1.front();        que1.pop();        int stat = cantor(cur.path);        if(vis2[stat])        {            pri(vis[stat]);            int k = vis2[stat];            while(pre[k].num != -1)            {                printf("%c",pre[k].ch);                k = pre[k].num;            }            printf("\n");            return;        }        for(int i = 0; i < 4; i++)        {            if(i==0&&cur.state<3)continue;             //up            if(i==1&&cur.state%3 == 2)continue;       //right            if(i==2&&cur.state>5)continue;            //down            if(i==3&&cur.state%3 == 0)continue;       //left            int posi = cur.state + dir[i];            tp = cur;            swap(tp.path[cur.state],tp.path[posi]);            int x = cantor(tp.path);            if(vis[x])                continue;            vis[x] = ++num;            tp.state = posi;            pre[num].ch = dire1[i];            pre[num].num = vis[stat];            que1.push(tp);        }        //反向搜索        last = que2.front();        que2.pop();        stat = cantor(last.path);        if(vis[stat])        {            pri(vis[stat]);            int k =vis2[stat];            while(pre[k].num!=-1)            {                printf("%c",pre[k].ch);                k=pre[k].num;            }            printf("\n");            return ;        }        for(int i = 0; i < 4; i++)        {            if(i==0&&last.state<3)continue;            if(i==1&&last.state%3==2)continue;            if(i==2&&last.state>5)continue;            if(i==3&&last.state%3==0)continue;            int posi = last.state + dir[i];            tp = last;            swap(tp.path[last.state],tp.path[posi]);            int x = cantor(tp.path);            if(vis2[x])                continue;            vis2[x] = ++num;            tp.state = posi;            pre[num].ch = dire2[i];            pre[num].num = vis2[stat];            que2.push(tp);        }    }    printf("unsolvable\n");}bool check(string a){    int num = 0;    for(int i = 0; i < 9; i++)    {        if(a[i] == '0' )            continue;        for(int j = i+1; j < 9; j++)        {            if(a[j] == '0') continue;            if(a[j] < a[i])                num++;        }    }    if(num & 1)        return true;    else        return false;}char ch;char a[100];int p[10];int main(){    while(gets(a))    {        int tnum = 0;        int n=strlen(a);        From.path="";        for(int i=0; i<n; i++)            if(a[i]!=' ')            {                if(a[i]=='x')                {                    From.state=tnum;                    From.path+='0';                }                else                    From.path+=a[i];                tnum++;            }        if(check(From.path))printf("unsolvable\n");        else              bfs(From);    }    return 0;}


③A*算法+康拓展开+奇偶剪枝

它把Dijkstra算法(靠近初始点的结点)和BFS算法(靠近目标点的结点)的信息块结合起来。走到终点的代价为f[n],主要由已经花费的代价g[n]和将要花费的代价h[n]决定,f[n] = g[n] + h[n],由于要找最短的路径,优先判定f[n]较小的。

而在本题中g[n]即是已经走过的步数,h[n]则是当前情况移动到->  123456780的最小步数.


#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <cstdlib>#include <queue>#include <algorithm>typedef long long ll;using namespace std;const int MAXN=362880;int fac[]= {1,1,2,6,24,120,720,5040,40320,362880};//         0!1!2!3! 4! 5!  6!  7!   8!    9!int vis[MAXN];int cantor(int s[]){    int sum=0;    for(int i=0; i<9; i++)    {        int num=0;        for(int j=0; j<i; j++)            if(s[j]>s[i])num++;        sum+=(num*fac[i]);    }    return sum;}struct node2{    int pre;    char ch;} pre[MAXN];struct node{    int matri[10];    int position;    int have,to;    int state;    bool operator < (const node a)const    {        return have+to>a.have+a.to;    }};char dire[5] = "urdl";int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};int fx[]={2,0,0,0,1,1,1,2,2},fy[]={2,0,1,2,0,1,2,0,1};int get_(node a){    int ans = 0;    for(int i = 0; i < 3; i++)        for(int j = 0; j < 3; j++){            if(a.matri[i*3+j]){                ans+=abs(i-fx[a.matri[i*3+j]])+abs(j-fy[a.matri[i*3+j]]);            }        }    return ans;}int fina[10];void pri(int k){    if(pre[k].pre == -1) return;    pri(pre[k].pre);    printf("%c",pre[k].ch);}void bfs(node cur){    priority_queue<node>que;    memset(vis,0,sizeof(vis));    vis[cur.state] = 1;    int tnum = 1;    pre[1].pre = -1;    for(int i = 0; i < 8; i++)        fina[i] = i+1;    fina[8] = 0;    int _ans = cantor(fina);    cur.have = 0;    que.push(cur);    while(!que.empty())    {        cur = que.top();        que.pop();        int x = cur.position/3;        int y = cur.position%3;        int num = cur.state;        if(num == _ans)        {            int k = vis[num];            pri(k);            printf("\n");            return ;        }        for(int i = 0; i < 4; i++)        {            int tx = x + dir[i][0];            int ty = y + dir[i][1];            if(tx < 0 || tx > 2 || ty < 0 || ty > 2)                continue;            node t = cur;            t.position =tx*3+ty;            t.matri[cur.position] = t.matri[t.position];            t.matri[t.position] = 0;            t.have++;            t.to = get_(t);            t.state =cantor(t.matri);            if(!vis[t.state])            {                vis[t.state] = ++tnum;                pre[tnum].pre = vis[num];                pre[tnum].ch = dire[i];                que.push(t);            }        }    }    printf("unsolvable\n");}bool check(int a[]){    int num = 0;    for(int i = 0; i < 9; i++)    {        if(a[i] == 0 )            continue;        for(int j = i+1; j < 9; j++)        {            if(a[j] == 0) continue;            if(a[j] < a[i])                num++;        }    }    if(num & 1)        return true;    else        return false;}char ch;int main(){    while(cin >> ch)    {        node from;        if(ch == 'x')        {            from.matri[0] = 0;            from.position = 0;        }        else            from.matri[0] = ch-'0';        for(int i = 1; i < 9; i++)        {            cin >> ch;            if(ch == 'x')            {                from.matri[i] = 0;                from.position = i;            }            else                from.matri[i] = ch-'0';        }        int ans = cantor(from.matri);        from.state = ans;        // printf("%d\n",ans);        if(check(from.matri))            printf("unsolvable\n");        else            bfs(from);    }    return 0;}



0 0
原创粉丝点击