HDOJ-1667/TJU4106 The Rotation Game(IDA*搜索)
2015-07-10 19:39
330 查看
今天下午学习了一下IDA*算法,收获还是不小的。
关于IDA*算法的和此题的题解见下面博客:
http://blog.csdn.net/urecvbnkuhbh_54245df/article/details/5856756
讲得非常详细,我的代码也算参考上面那篇博客的。
ID即迭代加深(Iterative Deepening),不断加深允许的最大DFS深度,避免了DFS一条到走到死的情况。虽然出现了某些状态重复搜索的弊端,但是从空间上讲,没有像BFS那样耗费大量内存。
A*算法使用估价函数进行剪枝。
同A*一样,难点是找到合适的估价函数。此题的估价函数剪枝为:如果8-中间最多的数的个数>限定的迭代深度-当前DFS深度则退出搜索。
关于IDA*算法的和此题的题解见下面博客:
http://blog.csdn.net/urecvbnkuhbh_54245df/article/details/5856756
讲得非常详细,我的代码也算参考上面那篇博客的。
ID即迭代加深(Iterative Deepening),不断加深允许的最大DFS深度,避免了DFS一条到走到死的情况。虽然出现了某些状态重复搜索的弊端,但是从空间上讲,没有像BFS那样耗费大量内存。
A*算法使用估价函数进行剪枝。
同A*一样,难点是找到合适的估价函数。此题的估价函数剪枝为:如果8-中间最多的数的个数>限定的迭代深度-当前DFS深度则退出搜索。
/************************************************************************* > File Name: 4106.cpp > Author:wangxin > Mail: > Created Time: 2015年07月10日 星期五 16时25分53秒 ************************************************************************/ #include<cstdio> #include<cstdlib> #include<cstring> using namespace std; int DEPTH,ansnum; //迭代深度,中间的数 int map[25]; //井字格 int midblocks[8]={7,8,9,12,13,16,17,18}; //位于井字中间位置的编号 char ansPath[100]; //存储搜索路径 //判断是否完成搜索 bool Judge(const int* state) { int i; for(i=1;i<=7;i++) if(state[midblocks[i]]!=state[midblocks[i-1]]) return false; return true; } //进行状态转换 void ChangeState(int *state,int a1,int a2,int a3,int a4,int a5,int a6,int a7) { int temp; temp=state[a1]; state[a1]=state[a2]; state[a2]=state[a3]; state[a3]=state[a4]; state[a4]=state[a5]; state[a5]=state[a6]; state[a6]=state[a7]; state[a7]=temp; } //计算中间出现最多的数字的个数 int CountMaxSameNum(const int* state) { int i,j,cntarr[4]; memset(cntarr,0,sizeof(cntarr)); for(i=0;i<8;i++) cntarr[state[midblocks[i]]]++; j=0; for(i=1;i<=3;i++) if(cntarr[i]>cntarr[j]) j=i; return cntarr[j]; } //DFS函数,返回值表示是否搜索到 curDepth表示当前的搜索深度,preDir表示上一步的变换方向 bool DFS(int *state, int curDepth, int preDir) { int i,j; int temp[25]; //IDA*估价函数剪枝,如果剩下的搜索深度不可能完成任务,不进行进一步搜索 if(DEPTH-curDepth < 8-CountMaxSameNum(state)) return false; //限定迭代深度 if(curDepth>DEPTH) return false; //枚举变换的方向 for(i=1;i<=8;i++) { //剪枝:连续的方向相反的变换是没有意义的 if((i==1 && preDir==6)||(i==6 && preDir==1)) continue; if((i==2 && preDir==5)||(i==5 && preDir==2)) continue; if((i==3 && preDir==8)||(i==8 && preDir==3)) continue; if((i==4 && preDir==7)||(i==7 && preDir==4)) continue; for(j=1;j<=24;j++) temp[j]=state[j]; switch(i) { case 1:ansPath[curDepth]='A'; ChangeState(temp, 1, 3, 7,12,16,21,23);break; case 2:ansPath[curDepth]='B'; ChangeState(temp, 2, 4, 9,13,18,22,24);break; case 3:ansPath[curDepth]='C'; ChangeState(temp,11,10, 9, 8, 7, 6, 5);break; case 4:ansPath[curDepth]='D'; ChangeState(temp,20,19,18,17,16,15,14);break; case 5:ansPath[curDepth]='E'; ChangeState(temp,24,22,18,13, 9, 4, 2);break; case 6:ansPath[curDepth]='F'; ChangeState(temp,23,21,16,12, 7, 3, 1);break; case 7:ansPath[curDepth]='G'; ChangeState(temp,14,15,16,17,18,19,20);break; case 8:ansPath[curDepth]='H'; ChangeState(temp, 5, 6, 7, 8, 9,10,11);break; default: printf("There is something wrong!"); } //如果检测到搜索成功,返回true if (Judge(temp)) { ansnum=temp[7]; ansPath[curDepth+1]='\0'; return true; } if (DFS(temp,curDepth+1,i)) return true; } return false; } void work() { int i,j,k,t,m,n; for(i=2;i<=24;i++) scanf("%d",&map[i]); if(Judge(map)) { printf("No moves needed\n"); printf("%d\n",map[7]); } else { //限定初始的迭代深度 DEPTH=1; while(1) { if(DFS(map,0,-1)) break; DEPTH++; //如果在当前迭代深度下没有搜出答案,加大搜索深度 } printf("%s\n",ansPath); printf("%d\n",ansnum); } } int main() { while(scanf("%d",&map[1]),map[1]) { work(); } return 0; }
相关文章推荐
- php中static静态关键字的使用
- jQuery 选择器
- 精益技术简历之道——改善技术简历的47条原则
- 不兼容结构的协调——适配器模式(一)
- 为什么需要ModelDriven
- UVA 12325 Zombie'sTreasureChest 宝箱 (分类枚举)
- Ubuntu相关操作
- 两个页面传参 js
- 对浮点数-整型数取绝对值
- java环境变量
- mac-tomcat设置
- mtk lcm驱动加载流程 (转载)
- BZOJ3023【中位数】
- COCOS2D-X 停止手打所有cpp文件到android.mk
- 1.3创建一个“HelloWorld"程序
- opencv中会引起内存泄露的情况
- [leetcode-59]spiral matrixII(java)
- 机器学习—广义线性模型(GLM)
- DEEP LEARNING IS THE FUTURE: Q&A WITH NAVEEN RAO OF NERVANA SYSTEMS
- 2.Add Two Numbers (List)