蓝桥杯BFS 移动方格的问题
2014-07-21 14:22
344 查看
这道题好像是某一届高职高专的最后一题,原题如下:
解题思路分析: 根据题目分析可知,每次能否移动某个方格的关键就是* 的位置,根据*的不同位置有不同的移动方法,而且每次移动可能都能有新的状态产生,当然可能会重复,由于每次都只能和* 相邻的位置元素交换而且要避免和前面的已经有过的状态重复,所以我当时拿到题目使用的是BFS搜索,我的思路是这样的:
首先我有一个队列,(char queue[710][6]; // 定义一个队列 总共排列710 总不可能超过710总情况),初始时放入ABCDE* 开始队列下标index指向初始情况队列总数countqueue=1如图:
开始的排列:
所以可以将2号和5号对换 得到 AB*DEC (没有出现过,入队列),也可以将4号和5号兑换 得到ABCD*E(没有出现 ,入队列)
此时队列的情况:
经过一次变化之后index加1 countqueue=3指向AB*DEC
此时可以将1,2 或则 2,5对换分别得到A*BDEC(没出现,入队列) 和 ABCDE*(重复,舍去)此次操作之后队列的index为2,countqueue=4:,如下图:
按照此步奏不断的重复 知道 index>=countqueue循环截止
程序代码如下(打印出所有可能移到的结果):
/* 10. 移动字母 2x3=6个方格中放入ABCDE五个字母,右下角的那个格空着。如图1所示。 和空格子相邻的格子中的字母可以移动到空格中,比如,图中的C和E就可以移动,移动后的局面分别是: A B D E C A B C D E 为了表示方便,我们把6个格子中字母配置用一个串表示出来,比如上边的两种局面分别表示为: AB*DEC ABCD*E 题目的要求是:请编写程序,由用户输入若干表示局面的串,程序通过计算,输出是否能通过对初始状态经过若干次移动到达该状态。可以实现输出1,否则输出0。初始状态为:ABCDE* 用户输入的格式是:先是一个整数n,表示接下来有n行状态。程序输出也应该是n行1或0 例如,用户输入: 3 ABCDE* AB*DEC CAED*B 则程序应该输出: 1 1 0 */
解题思路分析: 根据题目分析可知,每次能否移动某个方格的关键就是* 的位置,根据*的不同位置有不同的移动方法,而且每次移动可能都能有新的状态产生,当然可能会重复,由于每次都只能和* 相邻的位置元素交换而且要避免和前面的已经有过的状态重复,所以我当时拿到题目使用的是BFS搜索,我的思路是这样的:
首先我有一个队列,(char queue[710][6]; // 定义一个队列 总共排列710 总不可能超过710总情况),初始时放入ABCDE* 开始队列下标index指向初始情况队列总数countqueue=1如图:
开始的排列:
所以可以将2号和5号对换 得到 AB*DEC (没有出现过,入队列),也可以将4号和5号兑换 得到ABCD*E(没有出现 ,入队列)
此时队列的情况:
经过一次变化之后index加1 countqueue=3指向AB*DEC
此时可以将1,2 或则 2,5对换分别得到A*BDEC(没出现,入队列) 和 ABCDE*(重复,舍去)此次操作之后队列的index为2,countqueue=4:,如下图:
按照此步奏不断的重复 知道 index>=countqueue循环截止
程序代码如下(打印出所有可能移到的结果):
#include <cstdlib> #include <iostream> #include<algorithm> // 蓝桥杯移动方格的问题 using namespace std; char queue[710][6]; // 定义一个队列 int countqueue; // 记录队列的长度 int getIndex(char *a) // 找到* 的下标 { int result=0; for(int i=0;i<6;i++) if(a[i]=='*') { result=i; break; } return result; } bool equals(char *a,char *b) // 判断两个字符串是否相等 { bool sign=true; for(int i=0;i<6;i++) if(a[i]!=b[i]) { sign=false; break; } return sign; } bool inQueue(char *a) // 判断字符串是否存在队列中 { bool sign=false; // 不存在 for(int i=0;i<countqueue;i++) if(equals(a,queue[i])) { sign=true; // 存在 break; } return sign; } void pushqueue(char *a) // 进队列 { for(int i=0;i<6;i++) queue[countqueue][i]=a[i]; countqueue++; } char* swap(char* a,int m,int n) // 将m,n 下标的字符对换 { char* result=new char[6]; for(int i=0;i<6;i++) result[i]=a[i]; char t=result[m]; result[m]=result ; result =t; return result; } void getAllPerm() // 得到所有的排列 { int i=0; while(i<countqueue) { int index=getIndex(queue[i]); // 得到当前串中* 的下标 char* swapchar; // 通过交换得到的字符串 switch(index) // 根据* 号的下标 进行字符串的交换 { case 0: swapchar=swap(queue[i],0,1); if(!inQueue(swapchar)) // 如果字符串不在队列中,则加入到队列中 pushqueue(swapchar); swapchar=swap(queue[i],0,3); if(!inQueue(swapchar)) pushqueue(swapchar); break; // 错误 原因 case 1: swapchar=swap(queue[i],0,1); if(!inQueue(swapchar)) pushqueue(swapchar); swapchar=swap(queue[i],2,1); if(!inQueue(swapchar)) pushqueue(swapchar); swapchar=swap(queue[i],4,1); if(!inQueue(swapchar)) pushqueue(swapchar); break; // 错误 原因 case 2: swapchar=swap(queue[i],2,1); if(!inQueue(swapchar)) pushqueue(swapchar); swapchar=swap(queue[i],2,5); if(!inQueue(swapchar)) pushqueue(swapchar); break; // 错误 原因 case 3: swapchar=swap(queue[i],3,0); if(!inQueue(swapchar)) pushqueue(swapchar); swapchar=swap(queue[i],3,4); if(!inQueue(swapchar)) pushqueue(swapchar); break; // 错误 原因 case 4: swapchar=swap(queue[i],4,1); if(!inQueue(swapchar)) pushqueue(swapchar); swapchar=swap(queue[i],4,3); if(!inQueue(swapchar)) pushqueue(swapchar); swapchar=swap(queue[i],4,5); if(!inQueue(swapchar)) pushqueue(swapchar); break; // 错误 原因 case 5: swapchar=swap(queue[i],5,4); if(!inQueue(swapchar)) pushqueue(swapchar); swapchar=swap(queue[i],5,2); if(!inQueue(swapchar)) pushqueue(swapchar); break; // 错误 原因 } i++; } } int main(int argc, char *argv[]) { int n; char a[7]="abcde*"; pushqueue(a); getAllPerm(); cout<<"print: queue"<<endl; for(int i=0;i<countqueue;i++) { for(int j=0;j<6;j++) cout<<queue[i][j]<<" "; cout<<endl; } cout<<"共有"<<countqueue<<"条合格的记录"<<endl; cin>>n; int *result=new int ; for(int i=0;i<n;i++) { char test[6]; fflush(stdin); for(int j=0;j<6;j++) cin>>test[j]; if(inQueue(test)) result[i]=1; else result[i]=0; } for(int i=0;i<n;i++) { cout<<result[i]<<endl; } /* cout<<"print: queue"<<endl; for(int i=0;i<countqueue;i++) { for(int j=0;j<6;j++) cout<<queue[i][j]<<" "; cout<<endl; }*/ system("pause"); return EXIT_SUCCESS; }
相关文章推荐
- 蓝桥杯 历届试题 九宫重排 (八数码问题--康托展开去重 + bfs搜索)
- 蓝桥杯-算法提高 学霸的迷宫(BFS-倒向追踪输出移动方向)
- 学霸的迷宫-蓝桥杯算法提高-广搜 bfs 经典问题
- 蓝桥杯 算法提高 学霸的迷宫 经典BFS问题
- Excel中上下光标不可移动问题
- 移动硬盘常见问题的解决
- 移动SQL Server数据库时出现孤立用户权限问题的解决办法
- 如何解决移动应用中 PeekMessage 调用的资源利用问题
- 一组关于手持移动设备使用安全问题的统计数据
- 移动硬盘常见问题的解决
- 用asp.net开发移动WAP应用程序的问题
- 移动硬盘的常见问题
- 移动的验证码安全问题告诉移动网站后......,1860意指一般人不会这样做.
- 移动硬盘识别不了的问题
- 鼠标的光标不随鼠标移动问题的可能性分析
- 移动火柴问题的程序解法及生成算法
- 将窗口移动到前端, BringWindowToTop() 的问题
- 实现提交页面后滚动条自动移动问题
- 解决移动硬盘符不见的问题
- [Web]如何利用js库dom-drag.js最简单化实现移动图层和点击实现div居上问题