HDU 3567 Eight II 打表,康托展开,bfs,g++提交可过c++不可过 难度:3
http://acm.hdu.edu.cn/showproblem.php?pid=3567
相比Eight,似乎只是把目标状态由确定的改成不确定的,但是康托展开+曼哈顿为h值的A*和IDA*都不过,而且也不好控制字典序
换个角度想,虽然起始状态有很多,但是到底哪一位是1,哪一位是2不是最重要的,最重要的是和目标状态对应,所以可以把起始状态重新编码为"12345678"这种形式(先不考虑X),然后目标状态也对应过去,当考虑X的时候,我们可以认为起始状态只有9种,分别是'X'在各个位置的情况
利用bfs可以得到每种起始状态到对应的能够达到的所有目标状态的最短最小字典序转移方法,如果对每个状态都记录一个字符串肯定会MLE,所以只需要记录上一个状态到这一个状态转移所需要的操作即可
最后,对于每个目标状态,逆向推出状态转移序列,然后逆着输出即可
ps:一次处理3.6e6个状态,如果不用queue或者循环数组会MLE,如果不用g++提交而用c++提交会TLE
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cctype>
using namespace std;
const int base[9]={1,1,2,6,24,120,720,5040,40320};
const int dx[4]={1,0,0,-1};/转移方向,遵从字典序最小
const int dy[4]={0,-1,1,0};
const int maxh=362880;//每种开始状态所对应状态数
int des;//用于存储目标状态hash值,判断是否不需要转移
struct pnt{
int maz[3][3];
int ind;//标记起始状态的编号
int x,y;
int hashCode;
pnt(){
x=y=hashCode=-1;
}
pnt(char * str){
for(int i=0;i<9;i++){
if(str[i]=='X'){
maz[i/3][i%3]=9;
x=i/3;
y=i%3;
ind=i;
}
else maz[i/3][i%3]=str[i]-'0';
}
}
int gethashcode(){
int ans=0;
for(int i=0;i<9;i++){
int cnt=0;
for(int j=0;j<i;j++){
if(maz[j/3][j%3]>maz[i/3][i%3]){
cnt++;
}
}
ans+=base[i]*cnt;
}
return hashCode=ind*maxh+ans;
}
};
bool in(int tx,int ty){
return tx>=0&&tx<3&&ty>=0&&ty<3;
} int vis[maxh*10+1];//用于存储某状态是否已被遍历,并存储由何种操作得到该状态
int pre[maxh*10+1];//用于存储某状态由何种状态转移得到
queue<pnt> que;
char ans[maxh*10+1];//存储答案的逆序
char buff[300];//存储输入
pnt s,e;
int ind[10],indlen;//用于重新编码
bool input(){
if(scanf("%s",buff)!=1)return false;
indlen=0;//重新编码
for(int i=0;i<9;i++){
if(buff[i]>='0'&&buff[i]<='9'){
s.maz[i/3][i%3]=++indlen;
ind[buff[i]-'0']=indlen;
}
else{
s.maz[i/3][i%3]=9;
s.x=i/3;
s.y=i%3;
s.ind=i;
}
}
if(scanf("%s",buff)!=1)return false;
for(int i=0;i<9;i++){
if(buff[i]>='0'&&buff[i]<='9'){
e.maz[i/3][i%3]=ind[buff[i]-'0'];
}
else{
e.maz[i/3][i%3]=9;
e.x=i/3;
e.y=i%3;
}
}
e.ind=s.ind;//起始状态相同
des=e.gethashcode();
return true;
}
void bfs(){
while(!que.empty()){
pnt tp=que.front();que.pop();
int x=tp.x,y=tp.y;
for(int i=0;i<4;i++){
int tx=x+dx[i],ty=y+dy[i];
if(in(tx,ty)){
pnt nw=tp;
swap(nw.maz[tx][ty],nw.maz[x][y]);
nw.x=tx,nw.y=ty;
if(vis[nw.gethashcode()]==-1){
vis[nw.hashCode]=i;
pre[nw.hashCode]=tp.gethashcode();
que.push(nw);
}
}
}
}
}
void init(){
memset(vis,-1,sizeof(vis));
memset(pre,-1,sizeof(pre));
pnt s1=pnt("12345678X");//9种起始状态加入序列
vis[s1.gethashcode()]=-2;
que.push(s1);
pnt s2=pnt("1234567X8");
vis[s2.gethashcode()]=-2;
que.push(s2);
pnt s3=pnt("123456X78");
vis[s3.gethashcode()]=-2;
que.push(s3);
pnt s4=pnt("12345X678");
vis[s4.gethashcode()]=-2;
que.push(s4);
pnt s5=pnt("1234X5678");
vis[s5.gethashcode()]=-2;
que.push(s5);
pnt s6=pnt("123X45678");
vis[s6.gethashcode()]=-2;
que.push(s6);
pnt s7=pnt("12X345678");
vis[s7.gethashcode()]=-2;
que.push(s7);
pnt s8=pnt("1X2345678");
vis[s8.gethashcode()]=-2;
que.push(s8);
pnt s9=pnt("X12345678");
vis[s9.gethashcode()]=-2;
que.push(s9);
bfs();
}
int heap[maxh],sz;
int getans(pnt e){//逆序遍历
sz=0;
int last=e.gethashcode();
while(pre[last]>=0){
heap[sz++]=vis[last];
last=pre[last];
}
return sz;
}
void print(){
for(int i=sz-1;i>=0;i--){
switch(heap[i]){
case 0:
putchar('d');break;
case 1:
putchar('l');break;
case 2:
putchar('r');break;
case 3:
putchar('u');break;
}
}
putchar('\n');
}
int main(){
int T;
scanf("%d",&T);
init();
for(int ti=1;ti<=T;ti++){
input();
s.hashCode=s.gethashcode();
if(s.hashCode==des){
printf("Case %d: 0\n",ti);
puts("");
continue;
}
vis[s.hashCode]=-2;
int step=getans(e);
printf("Case %d: %d\n",ti,step);
print();
}
return 0;
}
HDU 3567 Eight II 打表,康托展开,bfs,g++提交可过c++不可过 难度:3的更多相关文章
- HDU 1043 & POJ 1077 Eight(康托展开+BFS+预处理)
Eight Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 30176 Accepted: 13119 Special ...
- HDU 1043 & POJ 1077 Eight(康托展开+BFS | IDA*)
Eight Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 30176 Accepted: 13119 Special ...
- HDU 3567 Eight II(八数码 II)
HDU 3567 Eight II(八数码 II) /65536 K (Java/Others) Problem Description - 题目描述 Eight-puzzle, which is ...
- HDU 1043 Eight(反向BFS+打表+康托展开)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目大意:传统八数码问题 解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各 ...
- HDU - 3567 Eight II (bfs预处理 + 康托) [kuangbin带你飞]专题二
类似HDU1430,不过本题需要枚举X的九个位置,分别保存状态,因为要保证最少步数.要保证字典序最小的话,在扩展节点时,方向顺序为:down, left, right, up. 我用c++提交1500 ...
- [HDOJ1043]Eight(康托展开 BFS 打表)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 八数码问题,因为固定了位置所以以目标位置开始搜索,把所有情况(相当于一个排列)都记录下来,用康托 ...
- hdu-1043(八数码+bfs打表+康托展开)
参考文章:https://www.cnblogs.com/Inkblots/p/4846948.html 康托展开:https://blog.csdn.net/wbin233/article/deta ...
- HDU1430 BFS + 打表 + 康托展开
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1430 , 一道比较好的题. 这道题要用到很多知识,康托展开.BFS.打表的预处理还要用到一一映射,做完 ...
- HDU 1430 魔板(康托展开+BFS+预处理)
魔板 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...
随机推荐
- [转载] YouCompleteMe
原文: http://blog.marchtea.com/archives/161#rd?sukey=fc78a68049a14bb2ba33c15948d34749e1eb616df07efe977 ...
- poj2780Linearity(多点共线)
链接 判断最多多少点在一条直线上, 可以枚举每一个点为坐标系的原点,其它点变成相应的位置,然后求得过原点及其点的斜率,排序找一下最多相同的. #include <iostream> #in ...
- Asp.net上传文件Request.files获取不到文件
使用ftp上传文件,并且Request.files获取文件,今天发现获取到的文件个数始终是0个,查了下原来form标签中需加入enctype=”multipart/form-data”,呵呵了 < ...
- python中if __name__ == '__main__'
python 中__name__ = '__main__' 的作用,到底干嘛的? 有句话经典的概括了这段代码的意义: “Make a script both importable and execut ...
- Linux的中断 & 中断和异常的区别
参考 http://www.yesky.com/20010813/192117.shtml 结构化程序设计思想认为:程序 = 数据结构 + 算法.数据结构体现了整个系统的构架,所以数据结构通常都是代码 ...
- 1.2G内存试玩RAMOS_XP
1.2G内存试玩RAMOS_XP1.为了防止做系统时出现意外,用Bootice把C盘MBR修改为Grub4dos,这样子系统如果失败,可以进入PE重做. 2.进入PE格式化C盘,格式化的时候勾选启用N ...
- java多线程下载网络图片
import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.BufferedReader ...
- 能源项目xml文件标签释义--<context:component-scan>
<context:component-scan base-package="com.xindatai.ibs" use-default-filters="false ...
- robotframework笔记13
变量 介绍 变量是不可或缺的功能机器人框架,他们可以 在大多数地方用于测试数据. 通常,他们使用 参数测试用例表中的关键字和关键字表,但是 也都设置允许变量的值. 一个正常的字 的名字 不能 指定一个 ...
- cssText在 IE6/7/8和chrome/Firefox/IE9+的不同
一,结尾没有分号 <div style="font-size:14px;">test</div> <script type="text/ja ...