zoukankan      html  css  js  c++  java
  • HDU1430 BFS + 打表 + 康托展开(转)

     题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1430 , 一道比较好的题。

      这道题要用到很多知识,康托展开、BFS、打表的预处理还要用到一一映射,做完受益匪浅。

      其实这道题也可以用双向BFS来写,思路也已经有了,过几天再来写。

      本文持续更新。


    先说搜索部分:

      对于魔板的每一个状态,都可以进行A、B、C三种操作,所以按照图论来讲,就是操作前的状态可以到达操作后的状态,所以就这样转换成了广搜问题。

      这里要注意一点,由于题目要求字典序最小的,所以搜索的时候要按照ABC的顺序来。

    再说康托展开:

      康托展开其实就是哈希的一种,即用一个数字来表示一个排列。比如说{A , B , C , D}的全排列中,ABCD对应的康托展开的值为0,ABDC对应的康托展开值为1...

      关于康托展开算法,具体见:http://www.cnblogs.com/mhpp/p/8039879.html

    关于打表预处理:

      由于魔板的所有状态都可以转换为“12345678”,所以这时就需要做一个映射:每组数据都有一个起始状态与目标状态,可以把起始状态用一种映射关系映射为“12345678”,然后用这种映射关系再去改一下终止状态。例如:初态为“12653487” , 目态为“12345678” ;这时映射后初态为“12345678”,即f[1] = 1 , f[2] = 2 , f[6] = 3 , f[5] = 4 , f[3] = 5 , f[4] = 6 , f[8] = 7 , f[7] = 8 ,按照这种映射关系目态应为“12564387”。代码应为:f[start[i] - '0'] = i ; end[i] = f[end[i] - '0'] + '0';

      有这样一个映射前提,就可以先用BFS预处理从“12345678”到其余所有状态的步骤,然后输入每组测试数据后进行转换,然后这时候就变成了求从“12345678”到映射后的目标状态的步骤的问题,这时按照存好的路径输出即可。

    BFS + 打表:

     1 #include <iostream>
     2 #include <queue>
     3 #include <string>
     4 #include <string.h>
     5 using namespace std;
     6 
     7 const int maxn = 50000 + 5;
     8 int vis[maxn];
     9 string ans[maxn];
    10 int fac[]={1 , 1 , 2 , 6 , 24 , 120 , 720 , 5040 , 40320};//1!,2!...8!
    11 int Cantor(string str)//康托展开
    12 {
    13     int ret = 0;
    14     int n = str.size();
    15     for(int i = 0 ; i < n ; i++) {
    16         int cnt = 0;
    17         for(int j = i ; j < n ; j++)//str[i]在子串中是第几大
    18             if(str[j] < str[i])
    19                 cnt++;
    20         ret += cnt * fac[n - i - 1];//累加
    21     }
    22     return ret;
    23 }
    24 void move_A(string &str)
    25 {
    26     for(int i = 0 ; i < 4 ; i++)
    27         swap(str[i] , str[7 - i]);
    28 }
    29 void move_B(string &str)
    30 {
    31     for(int i = 3 ; i > 0 ; i--)
    32         swap(str[i] , str[i - 1]);
    33     for(int i = 4 ; i < 7 ; i++)
    34         swap(str[i] , str[i + 1]);
    35 }
    36 void move_C(string &str)
    37 {
    38     char tmp = str[6];
    39     str[6] = str[5];
    40     str[5] = str[2];
    41     str[2] = str[1];
    42     str[1] = tmp;
    43 }
    44 void BFS(string str)//预处理,扩张由状态“12345678”,能到的所有状态
    45 {
    46     memset(vis , 0 , sizeof(vis));
    47     queue <string> que;
    48     que.push(str);
    49     int x = Cantor(str);
    50     vis[x] = 1;
    51     ans[x] = "";
    52     while(!que.empty()) {
    53         string u = que.front();
    54         que.pop();
    55         int i = Cantor(u);
    56         string tmp = u;
    57         move_A(tmp);
    58         int k = Cantor(tmp);
    59         if(!vis[k]) {
    60             vis[k] = 1;
    61             que.push(tmp);
    62             ans[k] = ans[i] + 'A';
    63         }
    64         tmp = u;
    65         move_B(tmp);
    66         k = Cantor(tmp);
    67         if(!vis[k]) {
    68             vis[k] = 1;
    69             que.push(tmp);
    70             ans[k] = ans[i] + 'B';
    71         }
    72         tmp = u;
    73         move_C(tmp);
    74         k = Cantor(tmp);
    75         if(!vis[k]) {
    76             vis[k] = 1;
    77             que.push(tmp);
    78             ans[k] = ans[i] + 'C';
    79         }
    80     }
    81 }
    82 int main()
    83 {
    84     int a[10];
    85     string s , e;
    86     string start = ("12345678");
    87     BFS(start);//预处理,打表
    88     while(cin >> s >> e)
    89     {
    90         for(int i = 0 ; i < 8 ; i++)//推导开始状态s,到标准开始状态“12345678”
    91                                    //的映射关系,存a中
    92             a[s[i] - '0'] = i + 1;
    93         for(int i = 0 ; i < 8 ; i++)//由映射关系存a及目标状态e推标准的目标状态。
    94             e[i] = a[e[i] - '0'] + '0';
    95         int k = Cantor(e);
    96         cout << ans[k] << endl;
    97     }
    98     return 0;
    99 }
    View Code
  • 相关阅读:
    stm32 复位后 引起引脚的变化,输出电平引起的问题
    利用jink的驱动软件j-flash 合并两个hex的方法,bootloader+app
    利用jink调试程序,时间不准的解决办法
    为什么你有10年经验,但成不了专家?
    第二章 信息的表示和处理
    Python人名独特性统计

    Python基本统计值计算
    VScode如何编译多个.C文件
    Python连续质数计算
  • 原文地址:https://www.cnblogs.com/mhpp/p/8040017.html
Copyright © 2011-2022 走看看