博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj1077(康托展开+bfs+记忆路径)
阅读量:6798 次
发布时间:2019-06-26

本文共 5148 字,大约阅读时间需要 17 分钟。

题意:就是说,给出一个三行三列的数组,其中元素为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
#include
#include
#include
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
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;}

 

转载地址:http://wduwl.baihongyu.com/

你可能感兴趣的文章
NetBeans在Apache基金会取得的进展
查看>>
Netflix实时流处理平台Keystone介绍
查看>>
一文带你快速读懂.NET CLI
查看>>
深入探索JVM自动资源管理
查看>>
实现TeX的算法:回首编程技术的过去三十年
查看>>
re:Invent大会第四天:为什么Lambda值得你更多关注?
查看>>
B端大数据应用的架构实践与思考
查看>>
Cascade:自动化测试“旅程”
查看>>
2018年十大云宕机事故盘点:主流无一幸免!
查看>>
美团开源实时监控系统 CAT 3.0 发布:多语言客户端及多项性能提升
查看>>
开源项目koa-router被叫卖,周下载10W+只要5000美元
查看>>
360首席安全官谭晓生宣布离职
查看>>
微软正式发布Azure Functions 2.0
查看>>
Swift 4.2进入最后开发阶段,为Swift 5铺平道路
查看>>
爱立信电信软件的持续交付
查看>>
Oracle提醒Java开发者们,很快就没有浏览器可以运行Applets了
查看>>
《The Age of Surge》作者访谈
查看>>
GitHub发布开源许可证使用情况
查看>>
网易云基于Prometheus的微服务监控实践
查看>>
mongodb常用命令
查看>>