转换地图 (康托展开+预处理+BFS)
Problem Description
1 2 3 4
8 7 6 5
对于这地图有三种具体操作方式:
A: 上下两行互换,如上图可变换为状态87654321
B: 每行同时循环右移一格,如上图可变换为41236785
C: 中间4个方块顺时针旋转一格,如上图可变换为17245368
根据所给的初状地图和终态地图,请给出完成转化的最少的变换步骤,若有多种变换方案则取字典序最小的那种。
Input
Output
SampleInput
12345678
17245368
12345678
82754631
SampleOutput
C
AC 最开始预处理了一下直接搜,本地爆炸。
然后想到了用康托展开打个表,然后。。。就AC了。
这里讲一下康托展开算法
X = An * (n-1)! + An-1 * (n-2)! + ... + A1 * 0!;
康拓展开就是求一个数字字符串在其全排列中的位置。
例如231这个数,全排列为123 132 213 231 312 321
所以231排在第4位,那么康托展开算法是如何求的呢。
例如求231的康托展开,从头至尾依次判断:
- 第一位数2,比2小的有一个,有1*2!
- 第二位数3,比3小的有两个,但2已经出现,有1*1!
- 第三位数1,有0*0!
累加起来就是2 + 1 = 3,表示比231小的有3个,所以231排在第4位。
代码实现的话就是:
int fac[] = {,,,,,,,,}; //i的阶乘
int kangtuo(int n,char a[]){ //n表示1~n个数,a数组表示数字
int i,j,t,res = ;
for(i = ; i < n; i++){
t = ;
for(j = i+; j < n; j++)
if(a[i] > a[j])
t++;
res += t*fac[n-i-];
}
return sum + ;
}
知道了康托展开后,就可以打表做了,值得一提的是这道题的预处理。因为题目输入两组字符串分别表示初始状态和结束状态,而我们打表是从12345678到各个状态的值,所以预处理我们把输入的初状态转成12345678,末状态也执行相应转换就可以了;
代码:
#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <sstream>
#include <iomanip>
#include <map>
#include <stack>
#include <deque>
#include <queue>
#include <vector>
#include <set>
#include <list>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <iterator>
#include <cmath>
#include <bitset>
#include <ctime>
#include <fstream>
#include <limits.h>
#include <numeric> using namespace std; #define F first
#define S second
#define mian main
#define ture true #define MAXN 1000000+5
#define MOD 1000000007
#define PI (acos(-1.0))
#define EPS 1e-6
#define MMT(s) memset(s, 0, sizeof s)
typedef unsigned long long ull;
typedef long long ll;
typedef double db;
typedef long double ldb;
typedef stringstream sstm;
const int INF = 0x3f3f3f3f; struct node{
string str,step;
}; bool vis[+];
int pos[],fac[] = {,,,,,,,,};
string ans[]; int fun(string a){
int i,j,t,sum = ;
for(i = ; i < ; ++i){
t = ;
for(j = i+; j < ; ++j)
if(a[i] > a[j])
++t;
sum += t*fac[-i-];
}
return sum+;
} void ma(string &s){
for(int i = ; i < ; ++i)
swap(s[i],s[i+]);
} string mb(string s){
string temp = s;
for(int i = ; i < ; ++i){
if(i== || i==)
temp[i]=s[i+];
else
temp[i]=s[i-];
}
return temp;
} void mc(string &s){
swap(s[],s[]);
swap(s[],s[]);
swap(s[],s[]);
} void bfs( string s ){
MMT(vis);
queue<node>q;
node pre,nxt; pre.str = s;
pre.step = "";
vis[fun(s)] = ;
ans[fun(s)] = pre.step;
q.push(pre); while(!q.empty()){
pre = q.front();
q.pop(); nxt = pre;
ma(nxt.str);
if(!vis[fun(nxt.str)]){
nxt.step += "A";
vis[fun(nxt.str)] = ;
ans[fun(nxt.str)] = nxt.step;
q.push(nxt);
} nxt.str = mb(pre.str);
if(!vis[fun(nxt.str)]){
nxt.step = pre.step + "B";
vis[fun(nxt.str)] = ;
ans[fun(nxt.str)] = nxt.step;
q.push(nxt);
} nxt = pre;
mc(nxt.str);
if(!vis[fun(nxt.str)]){
nxt.step += "C";
vis[fun(nxt.str)] = ;
ans[fun(nxt.str)] = nxt.step;
q.push(nxt);
}
}
} int main(){
ios_base::sync_with_stdio(false);
cout.tie();
cin.tie();
string s1,s2;
int k;
bfs("");
//12345678
//17245368
//12345678
//
while(cin>>s1>>s2){
swap(s1[],s1[]);
swap(s1[],s1[]);
swap(s2[],s2[]);
swap(s2[],s2[]);
for(int i = ; i < ; i++)
pos[s1[i]-''] = i+;
for(int i = ; i < ; i++)
s2[i] = pos[s2[i]-''];
k = fun(s2);
cout<<ans[k]<<endl;
}
return ;
}
其实康托展开也可以求逆运算,具体思想以及代码实现这里就不讲了=7=
转换地图 (康托展开+预处理+BFS)的更多相关文章
- UESTC 485 Game(康托展开,bfs打表)
Game Time Limit: 4000/2000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit Status t ...
- 康托展开+反向bfs
康托展开+反向bfs hdu 1043 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1043 #include <iostream> # ...
- ACM-康托展开+预处理BFS之魔板——hdu1430
魔板 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...
- HDU1430 BFS + 打表 + 康托展开
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1430 , 一道比较好的题. 这道题要用到很多知识,康托展开.BFS.打表的预处理还要用到一一映射,做完 ...
- hdu 1430 (BFS 康托展开 或 map )
第一眼看到这题就直接BFS爆搜,第一发爆了内存,傻逼了忘标记了,然后就改,咋标记呢. 然后想到用map函数,就8!个不同的排列,换成字符串用map标记.然后又交一发果断超时,伤心,最恨超时,还不如来个 ...
- HDU 1430 魔板(康托展开+BFS+预处理)
魔板 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...
- HDU 1043 & POJ 1077 Eight(康托展开+BFS+预处理)
Eight Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 30176 Accepted: 13119 Special ...
- hdu3567 八数码2(康托展开+多次bfs+预处理)
Eight II Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 130000/65536 K (Java/Others)Total S ...
- hdu1430魔板(BFS+康托展开)
做这题先看:http://blog.csdn.net/u010372095/article/details/9904497 Problem Description 在魔方风靡全球之后不久,Rubik先 ...
随机推荐
- Java学习|强引用,软引用,弱引用,幻想引用有什么区别?
在Java语言中,除了基本数据类型外,其他的都是指向各类对象的对象引用:Java中根据其生命周期的长短,将引用分为4类. 1 强引用 特点:我们平常典型编码Object obj = new Objec ...
- Codeforces 436D Pudding Monsters
题意简述 开始有无限长的一段格子,有n个格子种有布丁怪兽,一开始连续的布丁怪兽算一个布丁怪兽. 每回合你可以将一个布丁怪兽向左或右移动,他会在碰到第一个布丁怪兽时停下,并与其合并. 有m个特殊格子,询 ...
- Git原理入门简析
为了获得更好的阅读体验,建议访问原地址:传送门 前言: 之前听过公司大佬分享过 Git 原理之后就想来自己总结一下,最近一忙起来就拖得久了,本来想塞更多的干货,但是不喜欢拖太久,所以先出一版足够入门的 ...
- 在linux中部署项目并创建shell脚本
1.首先要在idea中父工程maven包下执行clean生成的target包 2.执行package打包,打包时候讲test勾去掉 3.将target包中生成的jar包cp出来 此处注意打包时必须要保 ...
- 如何使用Python连接ldap
如何使用Python连接ldap 好多使用ldap认证的软件都是Python的,比如superset和airflow, 好吧,他们都是airbnb家的.在配置ldap的时候可能会出现认证失败,你不知道 ...
- mysql数据库的水平拆分与垂直拆分
近端时间在面试,发现很多面试官或者面试都把数据的水平拆分合垂直拆分给搞混了,今天特意写了一篇博客来说说水平拆分和垂直拆分希望对程序猿们有所帮助. 数据库水平与垂直拆分: 垂直(纵向)拆分:是指按功能模 ...
- 03 requests模块基础
1. requests 模块简介 什么是requests 模块 requests模块是python中原生的基于网络请求的模块,功能强大,用法简洁高效.在爬虫领域中占据着半壁江山的地位.requests ...
- 程序与CPU
CPU中共有四大组件: 寄存器 控制器 运算器 时钟 寄存器:存取数值(存东西的) 控制器:负责将内存(寄存器)中的数据进行读入和写出(控制寄存器 协调者) 运算器:里面是逻辑运算单元,协助寄存器和控 ...
- 新手class名常用概括
容器: container 页头:header 内容:content/container 页面主体:main 页尾:footer 导航:nav 侧栏:sidebar 栏目:column ...
- vue项目中引入Sass
Sass作为目前成熟,稳定,强大的css扩展语言,让越来越多的前端工程师喜欢上它.下面介绍了如何在vue项目 中引入Sass. 首先在项目文件夹执行命令 npm install vue-cli -g, ...