<题目链接>

题目大意:
给出一个3×3的矩阵(包含1~8数字和一个字母x),经过一些移动格子上的数后得到连续的1~8,最后一格是x,要求最小移动步数。

解题分析:
本题用BFS来寻找路径,为了降低复杂度,用BFS从最终的目标状态开始处理,将所有搜索到状态以及对应的路径打表记录,然后对于输入的矩阵,直接查表输出答案 即可,本题还有一个难点,就是如何判断记录已经搜索过的状态,如果使用map+string(矩阵看成一维)会超时,所以我们这里用康拓展开式来记录状态。这道题比较玄学的地方在于如果更换dir 中四个方向的顺序,可能会WA,而在题目中没有对输出的字符串做任何限制,不知道这是为什么。

#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
typedef struct nn
{
char way; //记录操作
int fath; //记录父节点,用于记录路径
}node1; typedef struct nod
{
int aa[];
int n; //n为9在aa中的位置
int son; //记录aa的康拓展开式
}node2; int dir[][]={{,},{,-},{,},{-,}},fac[];
node1 Node[];//节点 void set_fac()//计算0到8的阶层
{
fac[]=;
for(int i=;i<=;i++)
fac[i]=fac[i-]*i;
} int cantor(int aa[])//康托展开,掌握康拓展开的方法
{
int ans=;
for(int i=;i<;i++)
{
int k=;
for(int j=i+;j<;j++)
if(aa[i]>aa[j])
k++;
ans+=k*fac[-i]; //i点以后比aa[i]小的数的个数*((n-i)-1)! 之和
}
return ans;
} void bfs(int a[])
{
queue<node2>Q;
node2 now,next; for(int i=;i<;i++) now.aa[i]=a[i];
now.n=;now.son=;
Node[now.son].fath=; //把最终父节点记为0,也就是本身
Q.push(now);
while(!Q.empty())
{
now=Q.front(); Q.pop();
for(int k=;k<;k++)
{
next=now;
int tx=now.n/+dir[k][];
int ty=now.n%+dir[k][];
if(ty>=&&tx>=&&ty<&&tx<)
{
next.n=tx*+ty; //得到移动后x的位置
int tem=next.aa[next.n]; //得到移动后该位置的原数字
next.aa[next.n]=next.aa[now.n];
next.aa[now.n]=tem; //将两个位置上的数字交换
next.son=cantor(next.aa); if(Node[next.son].fath==-) //为-1时表示这个点没有访问过,那么放入队列
{
Node[next.son].fath=now.son; //当前节点的父节点就是上一个节点
if(k==)Node[next.son].way='l';//一定要注意了,k=0是向右走,但我们是从终止状态往回搜,所以直接记录相反的方向
if(k==)Node[next.son].way='r';
if(k==)Node[next.son].way='u';
if(k==)Node[next.son].way='d';
Q.push(next);
}
}
}
}
} int main()
{
int i,j,s,ss[],a[]; for(i=;i<;i++)//目标状态
a[i]=i+; //建立目标一维矩阵,把x看成9 for(i=;i<;i++)
Node[i].fath=-;
set_fac(); //计算阶层
bfs(a); //将从最终状态能够延伸出去的所有状态以及对应路径提前打表记录 char str[];
while(gets(str))
{
for(i=,j=;str[i]!='\0';i++)//把字符串变成数子
{
if(str[i]=='x')
ss[j++]=; //把x变为数子9
else if(str[i]>=''&&str[i]<='')
ss[j++]=str[i]-'';
}
s=cantor(ss); //算出初态康托值
if(Node[s].fath==-) {printf("unsolvable\n");continue;} //不能变成目标,因为当从起点开始搜索的时候,fath表示搜索到某
//点时,上一个点的状态,所以,如果s.fath==-1时,表示这个矩阵根本就延伸不出去,不可能达到目标状态 while(s!=)
{
printf("%c",Node[s].way);
s=Node[s].fath;
}
printf("\n");
}
}

2018-09-06

hdu 1043 Eight (八数码问题)【BFS】+【康拓展开】的更多相关文章

  1. hdu 1043 pku poj 1077 Eight (BFS + 康拓展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 http://poj.org/problem?id=1077 Eight Time Limit: 1000 ...

  2. HDU 1043 Eight 八数码问题 A*算法(经典问题)

    HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...

  3. Hdu 1043 Eight (八数码问题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目描述: 3*3的格子,填有1到8,8个数字,还有一个x,x可以上下左右移动,问最终能否移动 ...

  4. 【HDU - 1043】Eight(反向bfs+康托展开)

    Eight Descriptions: 简单介绍一下八数码问题:在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图: 1 2 3 4 5 6 7 8   在上图中,由于右下角位置是空的 ...

  5. Eight (HDU - 1043|POJ - 1077)(A* | 双向bfs+康拓展开)

    The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...

  6. HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法

    先是这周是搜索的题,网站:http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6041 主要内容是BFS,A*,IDA*,还有一道K短路的,.. ...

  7. HDU 4531 bfs/康拓展开

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4531 吉哥系列故事——乾坤大挪移 Time Limit: 2000/1000 MS (Java/Othe ...

  8. [cdoj1380] Xiper的奇妙历险(3) (八数码问题 bfs + 预处理)

    快要NOIP 2016 了,现在已经停课集训了.计划用10天来复习以前学习过的所有内容.首先就是搜索. 八数码是一道很经典的搜索题,普通的bfs就可求出.为了优化效率,我曾经用过康托展开来优化空间,甚 ...

  9. poj 1077-Eight(八数码+逆向bfs打表)

    The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...

随机推荐

  1. .NET Windows API库(Cjwdev.WindowsApi)版本2.2发布

    https://blog.cjwdev.co.uk/2011/06/12/net-windows-api-library-cjwdev-windowsapi-vesion-2-2-released/# ...

  2. Pandas模块:表计算与数据分析

    目录 Pandas之Series Pandas之DataFrame 一.pandas简单介绍 1.pandas是一个强大的Python数据分析的工具包.2.pandas是基于NumPy构建的. 3.p ...

  3. 1283: 骨牌铺方格(zzuli)

    Problem Description 在2×n的一个长方形方格中,用一个1× 2的骨牌铺满方格,输入n ,输出铺放方案的总数.例如n=3时,为2× 3方格,骨牌的铺放方案有三种,如下图: Input ...

  4. checkbox 选中的id拼接长字符串

    需求描述:为了做一个批量操作,需要获取到checkbox选中的项的id,并且把选中的id拼接成字符串. 解决思路:先获取到checkbox选中项,然后拼接.(这tm不废话么),问题的关键就是获取che ...

  5. axure—日期函数

    日期函数 日期函数中实现倒计时的关键点:1)gettime()函数可以取到1970年1月1日的时间,我们用倒计时结束的时间减去当前时间就能得到倒计时需要循环显示的所有时间.2)此处的“d”是倒计时结束 ...

  6. Idea和PyCharm激活破解

    1. 先去百度去官网下载专业版IDE, Idea 和PyCharm激活方法一样 2. 下载破解包, 点击下载 3. 将下载的jar包放到这个安装目录的bin目录下面 4. 在bin目录下面的文件pyc ...

  7. 005-Python字典

    Python字典(dict) 字典是另一种可变容器模型,且可存储任意类型对象. 字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号{}中: ...

  8. C# 操作windows服务[启动、停止、卸载、安装]

    主要宗旨:不已命令形式操作windows服务 static void Main(string[] args) { var path = @"E:\开发辅助项目\WCF\WCF.Test\WC ...

  9. WCF三种通信方式

    一.概述 WCF在通信过程中有三种模式:请求与答复.单向.双工通信.以下我们一一介绍. 二.请求与答复模式 描述: 客户端发送请求,然后一直等待服务端的响应(异步调用除外),期间处于假死状态,直到服务 ...

  10. VMware搭建虚拟机服务器

    一.需求点描述: 1.在有路由器的情况下,能够通过固定的外网IP访问路由器中某台实体机中运行的虚拟机. 2.能够通过外网IP访问该虚拟机中的ftp.远程连接.iis.tomcat等. 二.原理分析: ...