题意:八数码,但是转移的方式是转动,一共十二种,有多组询问,初态唯一,终态不唯一。

题解:初态唯一,那么可以预处理出012345678的所有转移情况,然后将初态对012345678做一个映射,再枚举一下终态的所有情况,取最小值即可。

学了逆cantor展开,cantor展开是一个变进制数,每位上是原序列对应位置上的逆序值。那么求逆时候,就先除最大的位权得到对应位置上的逆序值,根据逆序值可以知道它在剩下的序列中第几大,然后标记它,迭代。状态转移有点麻烦。

#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
//#define localconst int maxn = 362880;
int d[maxn];
int fac[9] = { 1,1,2,6,24,120,720,5040,40320};//,362880
int St[9],Ed[9];int cantor(int *e) {int ret = 0;for(int i = 0; i < 9; i++) {int cnt = 0;for(int j = i+1; j < 9; j++)if(e[j] < e[i]) cnt++;ret += fac[8-i] * cnt;}return ret;
}void invCantor(int *a,int code)
{bool vis[10] = {0};for(int i = 0; i < 9; i++){int t = code/fac[8-i];int j;for( j = 0; j < 9 ; j++){if(!vis[j]){if(t == 0) break;t--;}}a[i] = j; vis[j] = 1;code %= fac[8-i];}
}int dir[12][9] = {
{2,0,1,3,4,5,6,7,8},{0,1,2,5,3,4,6,7,8},{0,1,2,3,4,5,8,6,7},
{1,2,0,3,4,5,6,7,8},{0,1,2,4,5,3,6,7,8},{0,1,2,3,4,5,7,8,6},
{6,1,2,0,4,5,3,7,8},{0,7,2,3,1,5,6,4,8},{0,1,8,3,4,2,6,7,5},
{3,1,2,6,4,5,0,7,8},{0,4,2,3,7,5,6,1,8},{0,1,5,3,4,8,6,7,2} };
queue<int> q;void BfsPre()
{memset(d,-1,sizeof(d) );d[0] = 0;q.push(0);while(q.size()){int u = q.front();q.pop();int tmp[9];invCantor(tmp,u);for(int i = 0; i < 12; i++){int tmp2[9];for(int j = 0; j < 9; j++){tmp2[j] = tmp[dir[i][j]];}int v = cantor(tmp2);if(~d[v]) continue;d[v] = d[u]+1;q.push(v);}}
}int query()
{int mp[9];for(int i = 0; i < 9; i++) { mp[St[i]] = i; }bool appear[9] = {0};for(int i = 0; i < 9; i++){if(~Ed[i]) appear[Ed[i] = mp[Ed[i]]] = 1;}int vec[9],sz = 0;for(int i = 0; i < 9; i++) {if(!appear[i]) vec[sz++] = i;}if(sz == 9)  return 0;if(sz == 0) return d[cantor(Ed)];
const int INF =  0x7fffffff;int ans = INF;int tmp[9];do{int j = 0;for(int i = 0; i < 9; i++){if(~Ed[i]) { tmp[i] = Ed[i]; }else { tmp[i] = vec[j++]; }}int Hash = cantor(tmp);if(~d[Hash]) ans = min(ans,d[Hash]);}while(next_permutation(vec,vec+sz));return ans!=INF? ans : -1;
}int main()
{
#ifdef localfreopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);
#endif // localint T;BfsPre();scanf("%d",&T);for(int k = 1; k <= T; k++){printf("Case #%d: ",k);for(int i = 0; i < 9; i ++){scanf("%d",St+i);St[i]--;}getchar();char buf[15];for(int i = 0; i < 3; i++){gets(buf);for(int j = 0; j < 5; j+=2){if('1'<=buf[j] && buf[j] <= '9'){Ed[i*3+j/2] = buf[j] - '1';}else Ed[i*3+j/2] = -1;}}int ans = query();if(~ans) printf("%d\n",ans);else printf("No Solution!\n");}return 0;
}

转载于:https://www.cnblogs.com/jerryRey/p/4678879.html

CDOJ 485 UESTC 485 Game (八数码变形,映射,逆cantor展开)相关推荐

  1. 【八数码问题】基于状态空间法的知识表示与状态搜索:无信息搜索(BFS/DFS) 启发式搜索(A*)

    前言 一.问题引入 二.状态空间法 1. 知识及其表示 2. 状态空间法定义 3. 问题求解 三.基于状态空间搜索法解决八数码问题 1. 八数码问题的知识表示 2. 状态空间图搜索 1. 无信息搜索 ...

  2. python解决八数码问题_A搜索算法(python)之八数码问题

    什么是启发式搜索算法 启发式搜索(Heuristically Search)又称为有信息搜索(Informed Search),它是利用问题拥有的启发信息来引导搜索,达到减少搜索范围.降低问题复杂度的 ...

  3. [算法分析与设计]拼图问题或八数码问题(搜索算法)

    [问题分析]: 拼图游戏实际上是八数码问题的小变形或者说其实就是八数码问题,针对八数码问题我们有三种搜索算法,分别是宽度优先搜索算法,深度优先搜索算法,启发式搜索算法A*.在解决路径类问题(即在一个二 ...

  4. 习题:八数码难题(双向BFS)

    八数码难题(wikioi1225) [题目描述] 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出 ...

  5. AI 八数码A_star算法问题-实验报告

    一 题目要求: 八数码问题的A星搜索算法实现         要求:设计估价函数,并采用c或python编程实现,以八数码为例演示A星算法的搜索过程,争取做到直观.清晰地演示算法,代码要适当加注释. ...

  6. 八数码问题及A*算法

    一.八数码问题 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个空格,与空格相邻的棋子可以移到空格中.要求解决的问题是: ...

  7. A*算法解决八数码问题 Java语言实现

    A*算法解决八数码问题 Java语言实现 参考文章: (1)A*算法解决八数码问题 Java语言实现 (2)https://www.cnblogs.com/beilin/p/5981483.html ...

  8. hdu1043 经典的八数码问题 逆向bfs打表 + 逆序数

    题意: 题意就是八数码,给了一个3 * 3 的矩阵,上面有八个数字,有一个位置是空的,每次空的位置可以和他相邻的数字换位置,给你一些起始状态 ,给了一个最终状态,让你输出怎么变换才能达到目的. 思路: ...

  9. 八数码 poj 1077 广搜 A* IDA*

    经典的八数码问题,有人说不做此题人生不完整,哈哈. 状态总数是9! = 362880 种,不算太多,可以满足广搜和A*对于空间的需求. 状态可以每次都动态生成,也可以生成一次存储起来,我用的动态生成, ...

  10. hdu 1043 ,pku 1077 Eight ,八数码问题

    某位神牛曾说过,此题是涉及到人生完不完整的一道题.. Goodness大牛曾总结了 八数码的八重境界 : http://www.cnblogs.com/goodness/archive/2010/05 ...

最新文章

  1. python基础代码库-python3.4第三方库的安装?python基础代码库
  2. 系统集成知识点整理(五)质量管理
  3. Oracle工具类-生成数据库现有Job的创建脚本
  4. 机器学习下一个万亿级的增长从哪来?
  5. 《深入理解Java虚拟机》第5章 调优案例分析与实战
  6. 总结几个 C 语言知识点
  7. 串口隔离内外网的通信协议设计
  8. ubuntu fuji xerox scanner扫描仪安装和使用
  9. 像《王者荣耀》一样红过
  10. 股票集合竞价什么意思?集合竞价时间及集合竞价技巧?
  11. [轉]ERP系统之比较——SAP、Oracle、BAAN、JDE、SSA
  12. 微信公众号开发(一)服务器及接口的配置
  13. linux下搜狗安装目录,搜狗输入法Linux版配置文件详解
  14. 什么是运营商大数据?您了解么?
  15. 函数指针定积分C语言,急!!!利用函数指针变量编写一个求定积分的通用函数,...
  16. 微信群控怎么结合到营销中
  17. 华硕无线网卡测试软件,华硕54M无线网卡WL-107g全面评测
  18. vi 和 vim 基本介绍
  19. 采购订单管理流程:定义、好处和步骤
  20. Python基础篇:函数的深入简出

热门文章

  1. 站长必须懂得技能:给网站设置ICO图标
  2. 声明式 webService 客户端(Feign) 介绍文档
  3. 几种常见的程序命名规则
  4. 12. 打印1到最大的n位数(C++版本)
  5. 24. Declear non-member functions when type conversions should apply to all parameters
  6. string进行大小写转换
  7. linux 扫描媒体库,如何扫描出Android系统媒体库中视频文件
  8. redis数据类型-字符串
  9. 模型算法_回归模型算法研究——ARMA模型
  10. java单元测试模拟输入_java – 单元测试:在定义模拟行为后调用...