Solution

这题的话直接上BFS就可以了,因为要输出方案,所以我们要开一个pre数组记录前驱,最后输出就可以了。

对于状态的记录,一般都用哈希来存,但因为这道题比较特殊,它是一个排列,所以我们可以利用康拓展开把空间压到9!。

康拓展开

一个排列的康拓展开表示的是字典序比他小的排列的个数,所以我们统计一下每一位后面有几个比它小的数字,乘上(n-i)!

inline int zx_hash(int x){
for(int i=;i>=;--i)a[i]=x%,x/=;
int num=;
for(int i=;i<=;++i){
int aa=;
for(int j=i+;j<=;++j)if(a[i]>a[j])aa++;
num+=aa*jie[-i];
}
return num;
}

逆康拓展开

我们不但要支持把排列映射成数字,还要支持把数字映射成排列。

具体操作就是从高到低按位考虑,令x=num/(n-i)!,那么可选集合中有x个数是比这一位上的数字小的,所以我们选择第x+1个数。

inline int anti_hash(int x){
int num=;
for(int i=;i<=;++i)vec[i]=i;int zo=;
for(int i=;i>=;--i){
int y=x/jie[i];
x=x%jie[i];
num=num*+vec[y];
for(int j=y;j<zo;++j)vec[j]=vec[j+];zo--;
}
return num;
}

不过康拓展开的复杂度是n^2的,但常数较小,遇到哈希排列之类的问题试一下。

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#define mm make_pair
#define N 12
using namespace std;
const int r1[]={,,,,,,,,,};
const int r2[]={,,,,,,,,,};
int jie[N],a[N],d1[N],d2[N],x,win,ans[],ji[],tag,tot,vec[];
struct node{
int first,second;
};
queue<node>q;
inline int zx_hash(int x){
for(int i=;i>=;--i)a[i]=x%,x/=;
int num=;
for(int i=;i<=;++i){
int aa=;
for(int j=i+;j<=;++j)if(a[i]>a[j])aa++;
num+=aa*jie[-i];
}
return num;
}
inline int anti_hash(int x){
int num=;
for(int i=;i<=;++i)vec[i]=i;int zo=;
for(int i=;i>=;--i){
int y=x/jie[i];
x=x%jie[i];
num=num*+vec[y];
for(int j=y;j<zo;++j)vec[j]=vec[j+];zo--;
}
return num;
}
int main(){
for(int i=;i<=;++i)scanf("%d",&a[i]),x=x*+a[i];jie[]=;int mem=x;
for(int i=;i<=;++i)jie[i]=jie[i-]*i;
win=zx_hash();
q.push(node{zx_hash(x),});
while(!q.empty()){
int u=q.front().first,nn=q.front().second;q.pop();
if(u==win){
printf("%d\n",nn);
tag=;
break;
}
x=anti_hash(u);
for(int i=;i>=;--i)d1[r1[i]]=x%,d2[r2[i]]=x%,x/=;
int x1=,x2=;
for(int i=;i<=;++i)x1=x1*+d1[i],x2=x2*+d2[i];
x1=zx_hash(x1);x2=zx_hash(x2);
if(!ji[x1])ji[x1]=u,q.push(node{x1,nn+});
if(!ji[x2])ji[x2]=u,q.push(node{x2,nn+});
}
if(!tag){
printf("UNSOLVABLE");
return ;
}
x=mem;x=zx_hash(x);
while(win!=x){
ans[++tot]=win;win=ji[win];
}
ans[++tot]=x;
for(int i=tot;i>=;--i){
int qq=anti_hash(ans[i]);
for(int j=;j>=;--j)a[j]=qq%,qq/=;
printf("%d %d %d\n%d %d %d\n%d %d %d\n\n",a[],a[],a[],a[],a[],a[],a[],a[],a[]);
}
return ;
}

[ZJOI2005]九数码游戏(BFS+hash)的更多相关文章

  1. [ZJOI2005]九数码游戏

    [ZJOI2005]九数码游戏 题目描述 输入输出格式 输入格式: 输入文件中包含三行三列九个数,同行的相邻两数用空格隔开,表示初始状态每个方格上的数字.初始状态不会是目标状态. 输出格式: 如果目标 ...

  2. 洛谷 P2578 [ZJOI2005]九数码游戏【bfs+康托展开】

    只有9!=362880个状态,用康托展开hash一下直接bfs即可 #include<iostream> #include<cstdio> #include<cstrin ...

  3. LG2578 「ZJOI2005」九数码游戏 bfs

    问题描述 LG2578 题解 用string+map去重. bfs即可. \(\mathrm{Code}\) #include<bits/stdc++.h> using namespace ...

  4. 洛谷 - P2578 - 九数码游戏 - bfs

    https://www.luogu.org/problemnew/show/P2578 一个挺搞的东西,用康托展开做记忆化搜索可以少一个log的查询. #include <bits/stdc++ ...

  5. 万圣节后的早晨&&九数码游戏——双向广搜

    https://www.luogu.org/problemnew/show/P1778 https://www.luogu.org/problemnew/show/P2578 双向广搜. 有固定起点终 ...

  6. HDU-1043 Eight八数码 搜索问题(bfs+hash 打表 IDA* 等)

    题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原 ...

  7. 【BZOJ】1054: [HAOI2008]移动玩具(bfs+hash)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1054 一开始我还以为要双向广搜....但是很水的数据,不需要了. 直接bfs+hash判重即可. # ...

  8. C#_界面程序_数码游戏

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  9. [BZOJ1054][HAOI2008]移动玩具 bfs+hash

    1054: [HAOI2008]移动玩具 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2432  Solved: 1355[Submit][Stat ...

随机推荐

  1. React Native之获取通讯录信息并实现类通讯录列表(ios android)

    React Native之获取通讯录信息并实现类通讯录列表(ios android) 一,需求分析 1,获取通讯录信息,筛选出通讯录里有多少好友在使用某个应用. 2,获取通讯录信息,实现类通讯录,可拨 ...

  2. javascript中的 return false和return true

    关于javascript中的 return false和return true,return 是javascript里函数返回值的关键字,一个函数内处理的结果可以使用return 返回,这样在调用函数 ...

  3. Mac上通过iterm 上传文件到服务器

    .安装 brew install lrzsz #这里以homebrew方式安装12.脚本 拉取 https://github.com/mmastrac/iterm2-zmodem 两个sh文件,将他们 ...

  4. Tomcat启用GZIP压缩,提升web性能

    一.前言 最近做了个项目,遇到这么一个问题:服务器返回给客户端的json数据量太大(大概65M),在客户端加载了1分多钟才渲染完毕,费时耗流量,用户体验极其不好.后来网上搜优化的方法,就是Http压缩 ...

  5. [转帖]tar高级教程:增量备份、定时备份、网络备份

    tar高级教程:增量备份.定时备份.网络备份 作者: lesca 分类: Tutorials, Ubuntu 发布时间: 2012-03-01 11:42 ė浏览 27,065 次 61条评论 一.概 ...

  6. [转帖]CentOS 6 服务器安全配置指南(通用)

    CentOS 6 服务器安全配置指南(通用) http://seanlook.com/2014/09/07/linux-security-general-settings/  发表于 2014-09- ...

  7. ArcGIS 添加 MarkerSymbol 弹出“图形符号无法序列化为 JSON”错误

    今天在做一个demo,向自定义图层中添加MarkerSymbol的时候,弹出“图形符号无法序列化为 JSON”错误,之前都没有出现过这个问题,我们首先来看一看我是怎样去添加图层,然后向图层中添加Gra ...

  8. Code::Blocks debug程序

    设置Settings--->Compiler, 打上勾: Produce debugging symbols [-g] 需要在settings->debugger settings-> ...

  9. java 中的打印流

    package cn.zhou; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.F ...

  10. XCTF 4th-WHCTF-2017 creakme

    exe文件 运行一下 随便输一下 ps.这个曹操身边的故事挺有意思的 但是没啥卵用....... 查一下壳无壳 ida载入 发现找不到main函数 直接看start感觉逻辑乱乱的(萌新求不喷..... ...