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 = ;
const int maxn = + ;
int vis[maxn];
string ans[maxn]; int fac[]={ , , , , , , , , };
int Cantor(string str)
{
int ret = ;
int n = str.size();
for(int i = ; i < n ; i++) {
int cnt = ;
for(int j = i ; j < n ; j++)
if(str[j] < str[i])
cnt++;
ret += cnt * fac[n - i - ];
}
return ret;
}
void move_A(string &str)
{
for(int i = ; i < ; i++)
swap(str[i] , str[ - i]);
}
void move_B(string &str)
{
for(int i = ; i > ; i--)
swap(str[i] , str[i - ]);
for(int i = ; i < ; i++)
swap(str[i] , str[i + ]);
}
void move_C(string &str)
{
char tmp = str[];
str[] = str[];
str[] = str[];
str[] = str[];
str[] = tmp;
}
void BFS(string str)
{
memset(vis , , sizeof(vis));
queue <string> que;
que.push(str);
int x = Cantor(str);
vis[x] = ;
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] = ;
que.push(tmp);
ans[k] = ans[i] + 'A';
} tmp = u;
move_B(tmp);
k = Cantor(tmp);
if(!vis[k]) {
vis[k] = ;
que.push(tmp);
ans[k] = ans[i] + 'B';
} tmp = u;
move_C(tmp);
k = Cantor(tmp);
if(!vis[k]) {
vis[k] = ;
que.push(tmp);
ans[k] = ans[i] + 'C';
}
}
}
int main()
{
int a[];
string s , e;
string start = ("");
BFS(start);
while(cin >> s >> e)
{
for(int i = ; i < ; i++)
a[s[i] - ''] = i + ;
for(int i = ; i < ; i++)
e[i] = a[e[i] - ''] + '';
int k = Cantor(e);
cout << ans[k] << endl;
}
return ;
}
HDU1430 BFS + 打表 + 康托展开的更多相关文章
- HDU1043 Eight(八数码:逆向BFS打表+康托展开)题解
Eight Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- hdu-1043(八数码+bfs打表+康托展开)
参考文章:https://www.cnblogs.com/Inkblots/p/4846948.html 康托展开:https://blog.csdn.net/wbin233/article/deta ...
- HDU 1043 Eight(反向BFS+打表+康托展开)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目大意:传统八数码问题 解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各 ...
- HDU 3567 Eight II 打表,康托展开,bfs,g++提交可过c++不可过 难度:3
http://acm.hdu.edu.cn/showproblem.php?pid=3567 相比Eight,似乎只是把目标状态由确定的改成不确定的,但是康托展开+曼哈顿为h值的A*和IDA*都不过, ...
- hdoj1043 Eight(逆向BFS+打表+康拓展开)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 思路: 由于自己对康拓展开用的太少,看到这个题没想到康拓展开,最开始打算直接转换为数字,但太占内 ...
- [HDOJ1043]Eight(康托展开 BFS 打表)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 八数码问题,因为固定了位置所以以目标位置开始搜索,把所有情况(相当于一个排列)都记录下来,用康托 ...
- UESTC 485 Game(康托展开,bfs打表)
Game Time Limit: 4000/2000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit Status t ...
- hdu1430魔板(BFS+康托展开)
做这题先看:http://blog.csdn.net/u010372095/article/details/9904497 Problem Description 在魔方风靡全球之后不久,Rubik先 ...
- HDU1430;魔板(BFS+康托展开)
传送门 题意 给出初始序列与终止序列,给出三种操作,问最少经过几次操作能使初始->终止,输出操作(字典序最小) 分析 字符串只有8个字符,使用康托展开. 1.BFS将所有序列从"123 ...
随机推荐
- 新安装的 ubuntu 下 make menuconfig 报错
环境:Ubtuntu 12.04 LTS 新安装的ubuntu 出现不能使用make menuconfig. 1.sudo apt-get update 更新软件 2.安装下面的软件 sudo apt ...
- java 调用SAP RFC函数错误信息
RFC接口调用SAP如果有异常会通过com.sap.mw.jco.JCO$Exception: 抛出异常 在开发中遇到的异常有如下 用户名密码可能是错误或者用户无权限,确认用户,必要时联系SAP负责人 ...
- SpringBoot2.0 基础案例(04):定时任务和异步任务的使用方式
一.定时任务 1.基本概念 按照指定时间执行的程序. 2.使用场景 数据分析 数据清理 系统服务监控 二.同步和异步 1.基本概念 同步调用 程序按照代码顺序依次执行,每一行程序都必须等待上一行程序执 ...
- thinkphp5 join使用注意
A表有id,name,time等字段, B表有id,type,uid,email,address等字段. A表中的id和B表中的uid对应. Db::table(A表)->alias('a') ...
- day20模块作业
1.模块化作业 1.回顾文件递归遍历. 默写一遍. 入口在: 当文件是个文件夹的时候 出口在: 文件是一个文件 2.计算时间差(用户输入起始时间和结束时间. 计算时间差(小时), 例如, 用户输入20 ...
- LeetCode初级算法(动态规划+设计问题篇)
目录 爬楼梯 买卖股票的最佳时机 最大子序和 打家劫舍 动态规划小结 Shuffle an Array 最小栈 爬楼梯 第一想法自然是递归,而且爬楼梯很明显是一个斐波拉切数列,所以就有了以下代码: c ...
- Cannot add or update a child row:
两个 表 数据 不一致... 含有 约束 的 表 中 所有 id 都应该 在 主 表 中 可以 找到---
- php与MySQL与echart综合使用
http://www.yinghualuowu.com/php/echart.html 创建table sex 有name num <?php ini_set('disp ...
- 了解Unix进程(3)
fork() 系统调用可以创建新的进程.然后查看进程ID和父进程ID使用getpid()和getppid()函数. 使用C语言描述: #include <unistd.h> #includ ...
- Git把旧仓库的分支拉到新仓库中
背景:项目新建了个git仓库(B仓库),放改版的新项目,现在运维所有项目构建都是在一个Jenkins里构建,然后拉镜像到相应服务器里,为了不让运维每次构建不同项目需要改git仓库地址,需要把原来项目仓 ...