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 ...
随机推荐
- JS 字符串编码函数(解决URL特殊字符传递问题):escape()、encodeURI()、encodeURIComponent()区别详解
javaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decod ...
- java SE (java Standard Edition)
14.10.22 学习java SE的Object: -------------------------------------15.11.18----
- UIImageView 的contentMode属性
UIViewContentModeScaleToFill UIViewContentModeScaleAspectFit UIViewContentModeScaleAspectFill UIView ...
- uva 11324 The Largest Clique
vjudge 上题目链接:uva 11324 scc + dp,根据大白书上的思路:" 同一个强连通分量中的点要么都选,要么不选.把强连通分量收缩点后得到SCC图,让每个SCC结点的权等于它 ...
- Android面试题整理【转载】
面试宝典(5) http://www.apkbus.com/android-115989-1-1.html 面试的几个回答技巧 http://blog.sina.com.cn/s/blog_ad ...
- 设置TextView下划线并响应点击事件(SpannableString)
下面是一个20行的完整Demo代码:基本原理是使用一个SpannableString并设置其ClickableSpan来响应点击事件. TextView useInfo = (TextView) fi ...
- [转]Oracle中INITRANS和MAXTRANS参数
每个块都有一个块首部.这个块首部中有一个事务表.事务表中会建立一些条目来描述哪些事务将块上的哪些行/元素锁定.这个事务表的初始大小由对象的INITRANS 设置指定.对于表,这个值默认为2(索引的IN ...
- Jquery_改变背景颜色
$(this).addClass("car_check").siblings().removeClass("car_check");//设置全部车辆为选中状态
- EL表达式 (详解)(转)
EL表达式 1.EL简介 1)语法结构 ${expression} 2)[]与.运算符 EL 提供.和[]两种运算符来存取数据. 当要存取的属性名称中包含一 ...
- 有关mipmaps
Mipmaps的作用是什么,仅仅是为了使屏幕三角形和纹理三角形的差异变小?有没有以空间换时间的理念? Mipmaps在生成一系列小的纹理样本时, 是如何从原始纹理采样的?即如何生成这些小的纹理样本.