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://blog.csdn.net/zhongkeli/article/details/6966805

关于打表预处理:

  由于魔板的所有状态都可以转换为“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 + 打表:

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <string.h>
#include <algorithm>
using namespace std;
#define LL __int64
#define eps 1e-8
#define INF 1e8
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int MOD = 2333333; 
const int maxn = 50000 + 5;
int vis[maxn];
string ans[maxn];

int fac[]={1 , 1 , 2 , 6 , 24 , 120 , 720 , 5040 , 40320};
int Cantor(string str)
{
    int ret = 0;
    int n = str.size();
    for(int i = 0 ; i < n ; i++) {
        int cnt = 0;
        for(int j = i ; j < n ; j++)
            if(str[j] < str[i])
                cnt++;
        ret += cnt * fac[n - i - 1];
    }
    return ret;
}
void move_A(string &str)
{
    for(int i = 0 ; i < 4 ; i++)
        swap(str[i] , str[7 - i]);
}
void move_B(string &str)
{
    for(int i = 3 ; i > 0 ; i--)
        swap(str[i] , str[i - 1]);
    for(int i = 4 ; i < 7 ; i++)
        swap(str[i] , str[i + 1]);
}
void move_C(string &str)
{
    char tmp = str[6];
    str[6] = str[5];
    str[5] = str[2];
    str[2] = str[1];
    str[1] = tmp;
}
void BFS(string str)
{
    memset(vis , 0 , sizeof(vis));
    queue <string> que;
    que.push(str);
    int x = Cantor(str);
    vis[x] = 1;
    ans[x] = "";
    while(!que.empty()) {
        string u = que.front();
        que.pop();
        int i = Cantor(u);

        string tmp = u;
        move_A(tmp);
        int k = Cantor(tmp);
        if(!vis[k]) {
            vis[k] = 1;
            que.push(tmp);
            ans[k] = ans[i] + 'A';
        }

        tmp = u;
        move_B(tmp);
        k = Cantor(tmp);
        if(!vis[k]) {
            vis[k] = 1;
            que.push(tmp);
            ans[k] = ans[i] + 'B';
        }

        tmp = u;
        move_C(tmp);
        k = Cantor(tmp);
        if(!vis[k]) {
            vis[k] = 1;
            que.push(tmp);
            ans[k] = ans[i] + 'C';
        }
    }
}
int main() 
{
    int a[10];
    string s , e;
    string start = ("12345678");
    BFS(start);
    while(cin >> s >> e)
    {
        for(int i = 0 ; i < 8 ; i++)
            a[s[i] - '0'] = i + 1;
        for(int i = 0 ; i < 8 ; i++)
            e[i] = a[e[i] - '0'] + '0';
        int k = Cantor(e);
        cout << ans[k] << endl;
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/H-Vking/p/4346004.html