• 【hdu1043 && poj 1077】八数码问题


    题目大意: 给你一个九宫格的初始状态(一个空格+数字1~8),让你按规则走变成目标状态(数字按顺序排序+空格在最后),如果有这样的解法输出其中一种少操作步骤解法,否则输出unsolvable。

    解题思路:超级经典的题目,解法超级多(据说有八重解法,和乾坤大挪移一样的,越到后面说明你越厉害),本来属于弱菜,只能达到三重。

                虽然上面两题题目是一样的,但是用的解法不一样,因为....蛋都碎了。

    poj1077:康托展开+双向bfs(32ms)

      数据比较弱,很多人都是用正向bfs水过去的,这里我用的是双向bfs,何谓双向bfs?简单的说就是起始状态和目标状态一起搜,轮着来。当在搜的过程中发现某个状态已经被另一不同开始状态搜过时,此时为最优解,即最优路径。双向bfs比单向bfs无论在时间上还是空间上都节省很多。

    联想一下bfs是从某一个点向四周扩散的,给你看个图就理解了。

    这里还要介绍一下如何保存状态:

    方法1:0-8,总共也就9位数,我们可以对应它进行int压缩,比如格子数从左到右从上到下为 2 3 1 5 x 8 4 6 7 , 可以将它进行压缩为2 3 1 5 8 4 6 7 5(x空格在第5位放在个位对应数字5,其余的对应int数前8位数)。

    方法2:9位数总共有9!个状态,可以利用到康托展开,何谓康托展开?比如数3 2 1 ,问你321在序列1 2 3全排列中是第几大,第一位是3,后面比它小的有1、2,则有2*2!,第二位数是2,后面比它小的有1,则有1*1!,加起来就是2*2!+1*1!=5,所以是第五大了。(具体:here

    View Code
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <queue>
      4 #include <algorithm>
      5 #include <cstring>
      6 using namespace std;
      7 
      8 const int maxn=366666;
      9 int visit1[maxn], visit2[maxn];
     10 int pp[9]= {1,1,2,6,24,120,720,5040,40430};
     11 int dir[4][2]= {0,1,0,-1,-1,0,1,0};
     12 char dd[4]= {'r','l','u','d'};
     13 int tp[maxn], st_aim, sd_aim;
     14 
     15 struct node
     16 {
     17     int pos0;
     18     int state;
     19     int s[9];
     20 };
     21 
     22 struct path
     23 {
     24     int pre;
     25     int dir;
     26 }path1[maxn], path2[maxn];
     27 
     28 int cantor(int ss[])
     29 {
     30     int sum=0;
     31     for(int i=0; i<9; i++)
     32     {
     33         int num=0;
     34         for(int j=i+1; j<9; j++)
     35             if(ss[j]<ss[i]) num++;
     36         sum+=num*pp[8-i];
     37     }
     38     return sum;
     39 }
     40 
     41 char change(char c)
     42 {
     43     if(c=='u') return 'd';
     44     else if(c=='d') return 'u';
     45     else if(c=='l') return 'r';
     46     else if(c=='r') return 'l';
     47 }
     48 
     49 void output1(int state)
     50 {
     51     int num=0;
     52     while(state!=st_aim) tp[num++]=path1[state].dir, state=path1[state].pre;
     53     for(int i=num-1; i>=0; i--) printf("%c",tp[i]);
     54 }
     55 
     56 void output2(int state)
     57 {
     58     while(state!=sd_aim) printf("%c",change(path2[state].dir)), state=path2[state].pre;
     59     puts("");
     60 }
     61 
     62 bool bfs(int ss[])
     63 {
     64     queue<node>p,q;
     65     node cur, tmp;
     66     memset(visit1,0,sizeof(visit1));
     67     memset(visit2,0,sizeof(visit2));
     68     for(int i=0; i<9; i++)
     69     {
     70         cur.s[i]=ss[i];
     71         if(ss[i]==0) cur.pos0=i;
     72     }
     73     cur.state=cantor(cur.s);
     74     q.push(cur);
     75     visit1[cur.state]=1, st_aim=cur.state;
     76     for(int i=0; i<8; i++) cur.s[i]=i+1;
     77     cur.s[8]=0, cur.pos0=8;
     78     cur.state=cantor(cur.s);
     79     p.push(cur);
     80     if(visit1[cur.state])  {  puts(""); return true; }
     81     visit2[cur.state]=1, sd_aim=cur.state;
     82     while(!q.empty()&&!p.empty())
     83     {
     84         if(!q.empty())
     85         {
     86             tmp=q.front();
     87             q.pop();
     88             for(int k=0; k<4; k++)
     89             {
     90                 int  x=tmp.pos0/3+dir[k][0];
     91                 int  y=tmp.pos0%3+dir[k][1];
     92                 if(x>=0&&x<=2&&y>=0&&y<=2)
     93                 {
     94                     for(int i=0; i<9; i++) cur.s[i]=tmp.s[i];
     95                     cur.pos0=3*x+y;
     96                     swap(cur.s[cur.pos0],cur.s[tmp.pos0]);
     97                     cur.state=cantor(cur.s);
     98                     if(visit2[cur.state])
     99                     {
    100                         output1(tmp.state);
    101                         printf("%c",dd[k]);
    102                         output2(cur.state);
    103                         return true;
    104                     }
    105                     if(!visit1[cur.state])
    106                     {
    107                         visit1[cur.state]=1;
    108                         path1[cur.state].pre=tmp.state;
    109                         path1[cur.state].dir=dd[k];
    110                         q.push(cur);
    111                     }
    112                 }
    113             }
    114         }
    115         if(!p.empty())
    116         {
    117             tmp=p.front();
    118             p.pop();
    119             for(int k=0; k<4; k++)
    120             {
    121                 int  x=tmp.pos0/3+dir[k][0];
    122                 int  y=tmp.pos0%3+dir[k][1];
    123                 if(x>=0&&x<=2&&y>=0&&y<=2)
    124                 {
    125                     for(int i=0; i<9; i++) cur.s[i]=tmp.s[i];
    126                     cur.pos0=3*x+y;
    127                     swap(cur.s[cur.pos0],cur.s[tmp.pos0]);
    128                     cur.state=cantor(cur.s);
    129                     if(visit1[cur.state])
    130                     {
    131                         output1(cur.state);
    132                         printf("%c",change(dd[k]));
    133                         output2(tmp.state);
    134                         return true;
    135                     }
    136                     if(!visit2[cur.state])
    137                     {
    138                         visit2[cur.state]=1;
    139                         path2[cur.state].pre=tmp.state;
    140                         path2[cur.state].dir=dd[k];
    141                         p.push(cur);
    142                     }
    143                 }
    144             }
    145         }
    146     }
    147     return false;
    148 }
    149 
    150 int main()
    151 {
    152     char str[30];
    153     int  s[10];
    154     while(gets(str))
    155     {
    156         int num=0;
    157         for(int i=0; str[i]; i++)
    158         {
    159             if(str[i]>='1'&&str[i]<='8') s[num++]=str[i]-'0';
    160             else if(str[i]=='x') s[num++]=0;
    161         }
    162         bool ok=bfs(s);
    163         if(!ok) puts("unsolvable");
    164     }
    165 }
    166 // 1 2 3 4 x 6 7 5 8

    hdu1043:  康托展开+逆序bfs(打表) (296ms) (为什么我写的双向bfs在这里过不了,难道是我写搓了?)

    View Code
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cmath>
      4 #include <algorithm>
      5 #include <cstring>
      6 using namespace std;
      7 
      8 const int maxn=366666;
      9 int visit[maxn];
     10 int pp[9]= {1,1,2,6,24,120,720,5040,40430};
     11 int dir[4][2]= {0,1,0,-1,-1,0,1,0};
     12 char dd[4]= {'r','l','u','d'};
     13 string path[maxn];
     14 
     15 struct node
     16 {
     17     int pos0;
     18     int state;
     19     int s[9];
     20     string path;
     21 } que[maxn];
     22 
     23 int cantor(int ss[])
     24 {
     25     int sum=0;
     26     for(int i=0; i<9; i++)
     27     {
     28         int num=0;
     29         for(int j=i+1; j<9; j++)
     30             if(ss[j]<ss[i]) num++;
     31         sum+=num*pp[8-i];
     32     }
     33     return sum;
     34 }
     35 
     36 void bfs()
     37 {
     38     int l=0, h=0;
     39     node cur, tmp;
     40     memset(visit,0,sizeof(visit));
     41     for(int i=0; i<8; i++) cur.s[i]=i+1;
     42     cur.s[8]=0, cur.pos0=8;
     43     cur.path="";
     44     cur.state=cantor(cur.s);
     45     que[l++]=cur;
     46     visit[cur.state]=1;
     47     path[cur.state]=cur.path;
     48     while(l!=h)
     49     {
     50         tmp=que[h++];
     51         for(int k=0; k<4; k++)
     52         {
     53             int  x=tmp.pos0/3+dir[k][0];
     54             int  y=tmp.pos0%3+dir[k][1];
     55             if(x>=0&&x<=2&&y>=0&&y<=2)
     56             {
     57                 for(int i=0; i<9; i++) cur.s[i]=tmp.s[i];
     58                 cur.pos0=3*x+y;
     59                // cout << cur.pos0 << "---" << tmp.pos0 << "----" << cur.path << "---"<<dd[k]<<endl;
     60                 swap(cur.s[cur.pos0],cur.s[tmp.pos0]);
     61                 cur.state=cantor(cur.s);
     62                 if(!visit[cur.state])
     63                 {
     64                     cur.path=tmp.path+dd[k];
     65                     visit[cur.state]=1;
     66                     que[l++]=cur;
     67                     path[cur.state]=cur.path;
     68                 }
     69             }
     70         }
     71     }
     72 }
     73 
     74 void output(string s)
     75 {
     76     int len=s.size();
     77     for(int i=len; i>=0; i--)
     78     {
     79         if(s[i]=='u') printf("d");
     80         else if(s[i]=='d') printf("u");
     81         else if(s[i]=='l') printf("r");
     82         else if(s[i]=='r') printf("l");
     83     }
     84     puts("");
     85 }
     86 
     87 int main()
     88 {
     89     char str[30];
     90     int  s[10];
     91     bfs();
     92     while(gets(str))
     93     {
     94         int num=0;
     95         for(int i=0; str[i]; i++)
     96         {
     97             if(str[i]>='1'&&str[i]<='8') s[num++]=str[i]-'0';
     98             else if(str[i]=='x') s[num++]=0;
     99         }
    100         int s_state=cantor(s);
    101         if(!visit[s_state]) puts("unsolvable");
    102         else output(path[s_state]);
    103     }
    104 }

    因为此题太经典,所以在此占个坑,以后慢慢来攻破这八层境界(A*+IDA*+>>>>)。

  • 相关阅读:
    PYTHON 函数总结
    PYTHON 模块总结
    python例题21--30
    python例题11--20
    python例题 1--10
    如何选中表格内同类名的某一行?
    table表格td内内容自动换行
    layer弹出层传值到父页面
    DIV内数据删除操作
    锚记搞定窗口滚动
  • 原文地址:https://www.cnblogs.com/kane0526/p/3020696.html
Copyright © 2020-2023  润新知