poj1077(康托展开+bfs+记忆路径)
题意:就是说,给出一个三行三列的数组,其中元素为1--8和x,例如:
1 2 3 现在,需要你把它变成:1 2 3 要的最少步数的移动方案。可以右移r,左移l,上移u,下移d
x 4 6 4 5 6
7 5 8 7 8 x
思路:这是赤裸裸的康托展开了吧?不知道康托展开的同学可以百度百科........好吧,其实我想说的是,这个题目怎么分析出,要用到康托展开的。首先,遇到这样的题目,元素比较少,又可以用到搜索,但是状态数比较多,也就是说,我需要找到一种方式来压缩这些状态,使得同一个状态不重复出现。额,说道这里,在不考虑时间、空间复杂度的情况下,的确可以直接开标记数组:vist[10][10][10][10][10][10][10][10][10],但是这样一来,会有许多重复的状态。有没有更好压缩状态的方法呢?是有的,进制压缩也是一种方法,只是对于这个题目不适用。那么还有康托展开,康托展开,可以使得这些状态压缩下来,只有9!个状态,如此就可以实现搜索了。
有的人说,广搜不能记录路径?这是错误的,广搜只要你清楚的记录这个状态的上个状态是什么,那么就可以记录路径,很明显只需要开个记录路径的搜索就ok了
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int t[10]= {1,1,2,6,24,120,720,5040,40320};
char ff[400000];
struct node
{
char ch[10];
int son;
int wz;
};
struct node1 //记录路径
{
char num;
int father;
} s[362883]; int deal(char str[]) //康托展开
{
int x[10],ans1=0;
for(int i=0; i<9; i++)
x[i]=str[i]-'0'; /*for(int i=0;i<9;i++)
printf("%d\t",x[i]);*/ for(int i=0; i<9; i++)
{
int k=0;
for(int j=i+1; j<9; j++)
if(x[i]>x[j])
k++;
ans1+=k*t[8-i];
//printf("%d %d %d\n",ans1,k,t[8-i]);
}
return ans1;
} int flag=0;
void bfs(char str[])
{
queue<node>q;
node p;
strcpy(p.ch,str);
p.ch[9]='\0';
p.son=deal(p.ch);
// puts(p.ch);
p.wz=8;
//printf("%d\n",p.son);
s[p.son].father=0; q.push(p); while(!q.empty())
{
//flag++;
//printf("%d\n",flag);
p=q.front();
q.pop();
int hang=p.wz/3;
int lie=p.wz%3;
{
int x=hang-1;
int y=lie;
{
int x=hang;
int y=lie+1;
if(x>=0&&x<3&&y>=0&&y<3&&(x*3+y)<=8)
{
node p1;
strcpy(p1.ch,p.ch);
p1.wz=x*3+y;
char zf=p1.ch[p.wz];
p1.ch[p.wz]=p1.ch[p1.wz];
p1.ch[p1.wz]=zf;
p1.ch[9]='\0';
p1.son=deal(p1.ch);
if(s[p1.son].father==-1)
{
s[p1.son].father=p.son;
s[p1.son].num='l';
q.push(p1);
}
}
} {
int x=hang;
int y=lie-1;
if(x>=0&&x<3&&y>=0&&y<3&&(x*3+y)<=8)
{
node p1;
strcpy(p1.ch,p.ch);
p1.wz=x*3+y;
char zf=p1.ch[p.wz];
p1.ch[p.wz]=p1.ch[p1.wz];
p1.ch[p1.wz]=zf;
p1.ch[9]='\0';
p1.son=deal(p1.ch);
if(s[p1.son].father==-1)
{
s[p1.son].father=p.son;
s[p1.son].num='r';
q.push(p1);
}
}
}
if(x>=0&&x<3&&y>=0&&y<3&&(x*3+y)<=8)
{
node p1;
strcpy(p1.ch,p.ch);
p1.wz=x*3+y;
char zf=p1.ch[p.wz];
p1.ch[p.wz]=p1.ch[p1.wz];
p1.ch[p1.wz]=zf;
p1.ch[9]='\0';
p1.son=deal(p1.ch);
if(s[p1.son].father==-1)
{
s[p1.son].father=p.son;
s[p1.son].num='d';
q.push(p1);
}
}
} {
int x=hang+1;
int y=lie;
if(x>=0&&x<3&&y>=0&&y<3&&(x*3+y)<=8)
{
node p1;
strcpy(p1.ch,p.ch);
p1.wz=x*3+y;
char zf=p1.ch[p.wz];
p1.ch[p.wz]=p1.ch[p1.wz];
p1.ch[p1.wz]=zf;
p1.ch[9]='\0';
p1.son=deal(p1.ch);
if(s[p1.son].father==-1)
{
s[p1.son].father=p.son;
s[p1.son].num='u';
q.push(p1);
}
}
} }
}
int main()
{
char str[10]= {'1','2','3','4','5','6','7','8','0'};
for(int i=0; i<362883; i++)
{
s[i].father=-1;
}
//printf("%d\n",flag);
bfs(str);
char ss[10][10];
char tt[10];
scanf("%s",ss[0]);
{
if(ss[0][0]!='x')
tt[0]=ss[0][0];
else
tt[0]='0'; //把x转化为数字0
for(int i=1; i<9; i++)
{
scanf("%s",ss[i]);
if(ss[i][0]!='x')
tt[i]=ss[i][0];
else
tt[i]='0';
}
tt[9]='\0';
//puts(tt);
int ans=deal(tt);
int cnt=0;
flag=0;
while(ans!=0) //回溯路径
{
ff[cnt++]=s[ans].num;
ans=s[ans].father;
if(ans==-1)
{
flag=1;
break;
}
}
int i=0;
if(flag==0)
{
while(cnt>i)
printf("%c",ff[i++]);
}
else printf("unsolvable");
printf("\n");
}
return 0;
}
poj1077(康托展开+bfs+记忆路径)的更多相关文章
- hdu 1430(BFS+康托展开+映射+输出路径)
魔板 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- hdu1043Eight (经典的八数码)(康托展开+BFS)
建议先学会用康托展开:http://blog.csdn.net/u010372095/article/details/9904497 Problem Description The 15-puzzle ...
- HDU 1430 魔板(康托展开+BFS+预处理)
魔板 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...
- HDU 1043 & POJ 1077 Eight(康托展开+BFS+预处理)
Eight Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 30176 Accepted: 13119 Special ...
- HDU 3567 Eight II 打表,康托展开,bfs,g++提交可过c++不可过 难度:3
http://acm.hdu.edu.cn/showproblem.php?pid=3567 相比Eight,似乎只是把目标状态由确定的改成不确定的,但是康托展开+曼哈顿为h值的A*和IDA*都不过, ...
- [HDOJ1043]Eight(康托展开 BFS 打表)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 八数码问题,因为固定了位置所以以目标位置开始搜索,把所有情况(相当于一个排列)都记录下来,用康托 ...
- HDU 1043 & POJ 1077 Eight(康托展开+BFS | IDA*)
Eight Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 30176 Accepted: 13119 Special ...
- poj2965(位运算压缩+bfs+记忆路径)
题意:有个4*4的开关,里面有着16个小开关 -+-- ---- ---- '+'表示开关是关着的,'-'表示开关是开着的,只有所有的开关全被打开,总开关才会被打开.现在有一种操作,只要改变某个开关, ...
- HDU 1043 Eight 【经典八数码输出路径/BFS/A*/康托展开】
本题有写法好几个写法,但主要思路是BFS: No.1 采用双向宽搜,分别从起始态和结束态进行宽搜,暴力判重.如果只进行单向会超时. No.2 采用hash进行判重,宽搜采用单向就可以AC. No.3 ...
随机推荐
- 进阶之路(中级篇) - 017 有关于Arduino 驱动舵机及相关问题
/********************************* 代码功能:通过串口控制电机 使用函数: Serial.available(); //判断串口是否接收到数据 Serial.prin ...
- MachineLearning之Logistic回归
一.概述 假设现在有一些数据点,我们用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称为回归: 利用Logistic回归进行分类的主要思想是: 根据现有数据对分类边界线建立回归公式, ...
- js 对文件操作
下面是对此知识的系统介绍(转自互联网): Javascript是网页制作中离不开的脚本语言,依靠它,一个网页的内容才生动活泼.富有朝气.但也许你还没有发现并应用它的一些更高级的功能吧?比如,对文件和文 ...
- block(五)用法
最近又从网上找了点block用法的博客,供大家参考. Block简介: Block的实际行为和Function很像,最大的差别是在可以存取同一个Scope的变量值.Block实体形式如下: ^(传入参 ...
- c#代码 天气接口 一分钟搞懂你的博客为什么没人看 看完python这段爬虫代码,java流泪了c#沉默了 图片二进制转换与存入数据库相关 C#7.0--引用返回值和引用局部变量 JS直接调用C#后台方法(ajax调用) Linq To Json SqlServer 递归查询
天气预报的程序.程序并不难. 看到这个需求第一个想法就是只要找到合适天气预报接口一切都是小意思,说干就干,立马跟学生沟通价格. 不过谈报价的过程中,差点没让我一口老血喷键盘上,话说我们程序猿的人 ...
- golang学习笔记 ----读写文件
使用io/ioutil进行读写文件 ioutil包 其中提到了两个方法: func ReadFile func ReadFile(filename string) ([]byte, error) Re ...
- MFC添加自定义窗口消息
原文链接: http://www.cnblogs.com/smartvessel/archive/2011/07/18/2109472.html 1. 在头文件stdafx.h中增加一个自定义消息宏 ...
- T-SQL查询进阶--理解SQL Server中索引的概念,原理以及其他
简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能.但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索 ...
- H5 设备方向及运动API
传送门:https://blog.csdn.net/Panda_m/article/details/57515195 入门的demo: <!DOCTYPE html> <html l ...
- Nuxt 开发环境不支持ip访问?
传送门:https://nuxtjs.org/faq/host-port 开发模式下不支持ip访问? 打开package.json,添加如下配置,然后重启即可. "config": ...