HDU 1430 DFS + 康托展开 + 映射处理 +预处理!

第一点:


模板操作是对于8个字母进行操作的,直接处理起来特别麻烦。对于这种有顺序要求的不重复分字符串处理,我们可以考虑康托展开,用一个数字来替代整个字符串。

康拓展开:http://blog.csdn.net/zhongkeli/article/details/6966805 

其实就是按照事先的约定,把一个字符串变成一个数字。


第二点:


为了省时间,我们进行预处理,我们需要固定初始值不变,之后枚举它到其他所有状态的变化过程。但是题目给出的初始值不是固定的,所以我们要进行映射。

我们预处理就固定ABCDEFGH这个序列到其他序列的变化了。那么我们需要对所有输入进行处理,变成ABCDEFGH


假设输入为  EFGHABCD  要求变成HABCDEFG

对于第一个E,我们要让他变为A,相应的输出列中的E也要变成A。也就是AFGHABCD/ HABCDAEFG

最后变完ABCDEFGH   DEFGHABC

按照预处理的,我们直接输出ans【“DEFGHABC”】即可,当然这个DEFGHABC也要康拓成一个数。


第三点:


就是BFS了,对于一个String,进行三种不同的操作,之后检查操作完的String的康拓数的vis是否访问过,没有求更新,就是普通的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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值