相关文章
更多最近更新
更多AI八数码问题 Stack Overflow
2019-03-25 13:52|来源: 网路
AI课本八数码问题,我是用广度优先搜索,用Ismatch来记录状态是否已经遍历,个人感觉算法基本没错吧!可是编译程序的时候只要步数长一点(5步可以输出)就没有输出,用Debug调试显示是:Stack Overflow。我看了很久的代码,也没有搞懂需要在哪里做优化。希望大家看下给点意见。谢谢
ps:用“在link option中增加/stack”这种方法可以实现步长到27,我是想知道是否有更好的方法可以优化代码
#include <stdio.h> #include <string.h> #define M 362881 bool IsAnswer = false; bool Ismatch[M];//标记是否已经遍历过 int tos,len;//队列指针tos,长度len int tt[9]={1,1,2,6,24,120,720,5040,40320}; char dest[10];//目标状态 char tmap[10]; enum dir{up,down,left,right,none}; struct { int dir; int t; }path[M];//记录路径 struct eightnum{ char map[10]; int x,y; int father; dir myDir;//父节点移动的方向 }num[M]; eightnum temp; void back_push(eightnum _num)//push { strcpy(num[len].map, _num.map); num[len].x = _num.x; num[len].y = _num.y; num[len].father = _num.father; num[len].myDir = _num.myDir; ++len; } eightnum front_pop()//pop { tos++; if(tos<len) return num[tos]; else printf("Wrong about the queue!\n"); } int getHash(char _map[])//获取hash { int hash; int k,l; hash = 0; int count = 0; for(k=0;k<9;++k){ count = 0; for(l = 0 ; l < k ;++ l){ if(_map[k]<_map[l]) count++; } hash += count*tt[k]; } return hash; } int ReverseNum(char _map[])//逆序数 { int k,l; int count = 0; for(k=0;k<9;++k){ for(l = 0 ; l < k ;++ l){ if(_map[k] == '0') continue; else if(_map[k]<_map[l]) count++; } } return count; } void DFS(eightnum _tmp)//dfs { getHash(_tmp.map); if(strcmp(_tmp.map,dest)==0){//find the answer IsAnswer = true; printf("Find the path!\n"); return; } else if(len>=M){//flow printf("Above Flow!"); return ; } else{ //down if( _tmp.x != 2){ strcpy(tmap,_tmp.map); char m_tmp; m_tmp = tmap[_tmp.x*3+_tmp.y]; tmap[_tmp.x*3+_tmp.y] = tmap[(_tmp.x+1)*3+_tmp.y]; tmap[(_tmp.x+1)*3+_tmp.y] = m_tmp; int m_hash = getHash(tmap); if(Ismatch[m_hash]==false){ Ismatch[m_hash] = true; strcpy(temp.map,tmap); temp.x = _tmp.x + 1; temp.y = _tmp.y; temp.father = tos; temp.myDir = down; back_push(temp); } } //right if( _tmp.y != 2 ){ strcpy(tmap,_tmp.map); char m_tmp; m_tmp = tmap[(_tmp.x)*3+_tmp.y]; tmap[(_tmp.x)*3+_tmp.y]= tmap[(_tmp.x)*3+_tmp.y+1]; tmap[(_tmp.x)*3+_tmp.y+1] = m_tmp; int m_hash = getHash(tmap); if(Ismatch[m_hash]==false){ Ismatch[m_hash] = true; strcpy(temp.map,tmap); temp.x = _tmp.x; temp.y = _tmp.y+1; temp.father = tos; temp.myDir = right; back_push(temp); } } //up if(_tmp.x != 0){ strcpy(tmap,_tmp.map); char m_tmp; m_tmp = tmap[_tmp.x*3+_tmp.y]; tmap[_tmp.x*3+_tmp.y] = tmap[(_tmp.x-1)*3+_tmp.y]; tmap[(_tmp.x-1)*3+_tmp.y] = m_tmp; int m_hash = getHash(tmap); if(Ismatch[m_hash]==false){ Ismatch[m_hash] = true; strcpy(temp.map,tmap); temp.x = _tmp.x - 1; temp.y = _tmp.y; temp.father = tos; temp.myDir = up; back_push(temp); } } //left if( _tmp.y != 0 ){ strcpy(tmap,_tmp.map); char m_tmp; m_tmp = tmap[_tmp.x*3+_tmp.y]; tmap[_tmp.x*3+_tmp.y]= tmap[(_tmp.x)*3+_tmp.y-1]; tmap[(_tmp.x)*3+_tmp.y-1] = m_tmp; int m_hash = getHash(tmap); if(Ismatch[m_hash]==false){ Ismatch[m_hash] = true; strcpy(temp.map,tmap); temp.x = _tmp.x; temp.y = _tmp.y-1; temp.father = tos; temp.myDir = left; back_push(temp); } } } eightnum m_tmp = front_pop(); DFS(m_tmp); } void myDisplay(char _map[]){//display int ii; for(ii=0;ii<9;++ii){ if(0==ii%3) printf("\n"); if(_map[ii] == '0') printf(" "); else printf("%c ",_map[ii]); } printf("\n-----------------------------\n"); } int main() { char input[10] ;//输入 strcpy(input,"283164705"); strcpy(dest,"123804765"); int i; tos = -1; len = 0; strcpy(temp.map,input); printf("原始状态:\n"); myDisplay(input); for(i=0;i<M;++i) Ismatch[i] = false; if( ReverseNum(input)%2 != ReverseNum(dest)%2){ printf("Not exist the answer!\n"); return 1; } for(i=0;i<10;++i){ if(temp.map[i] == '0'){ Ismatch[getHash(temp.map)] = true; temp.x = i/3; temp.y = i%3; temp.father=-1; temp.myDir = none; back_push(temp); break; } } eightnum _tmp = front_pop(); DFS(_tmp); int kk = 0; if (IsAnswer){ int ff = tos ; while( num[ff].father != -1){ path[kk].dir = num[ff].myDir; path[kk].t = ff; kk++; //printf("%d",num[ff].myDir); ff = num[ff].father; } } for(i=kk-1;i>=0;--i) { if(path[i].dir==0){ printf("down-->"); myDisplay(num[path[i].t].map); } else if(path[i].dir==1){ printf("up-->"); myDisplay(num[path[i].t].map); } else if(path[i].dir==2){ printf("right-->"); myDisplay(num[path[i].t].map); } else if(path[i].dir==3){ printf("left-->"); myDisplay(num[path[i].t].map); } } return 0; }
ps:用“在link option中增加/stack”这种方法可以实现步长到27,我是想知道是否有更好的方法可以优化代码
相关问答
更多-
什么是堆栈溢出?(What is a stack overflow?)[2023-11-24]
维基百科 : 在软件中,当调用堆栈使用太多内存时,会发生堆栈溢出。 在许多编程语言中,调用堆栈包含有限的内存量,通常在程序开始时确定。 该堆栈是一个数据结构,用于记录程序的子例程在完成执行时应将控制权返回给的点的记录。 当子程序被调用时,返回地址被压入栈中,当子程序结束执行时,返回地址被从栈中取出 。 如果有许多子程序并且堆栈中没有空间,则会发生堆栈溢出。 同样在堆栈中的目的是存储局部变量,所以如果局部变量太大,更可能堆栈没有空间来存储它,如果这种情况发生堆栈溢出。 当DrawLine子程序从另一个名为Dr ... -
所以看起来只有一些设备有这个问题; 我不知道为什么会这样,但这是我的工作。 try { // Transition drawable with a transparent drawable and the final bitmap TransitionDrawable td = new TransitionDrawable(new Drawable[] { aImageView.getDrawable(), ...
-
处理堆栈溢出(stack overflow under processing)[2022-04-09]
如果您只是想知道是否有办法设置堆栈大小,那么谷歌就是您的朋友。 处理是用Java编写的,因此google搜索“java set stack size”这样的东西将是一个很好的起点。 实际上,StackOverflow多次询问了这个问题: 如何增加Java堆栈大小? Java堆栈溢出错误 - 如何在Eclipse中增加堆栈大小? Java Applet:增加堆栈大小 java设置最大堆栈大小 Java默认堆栈大小 但是,由于您正在使用Processing,因此您必须将其导出为可运行的jar,或者从eclips ... -
看看http://www.osqa.net/ 。 我相信这是基于python / Django的。 Take a look at http://www.osqa.net/. It's python/Django based I believe.
-
他们使用名为WMD Markdown Editor的HTML编辑器。 They use an HTML editor called WMD Markdown Editor.
-
Stack Overflow java(Stack Overflow java)[2022-10-18]
不,将其声明为static不会导致无限循环。 这是为什么。 静态变量在类加载时间内初始化。 因此,当您的类第一次加载时,编译器将为静态变量创建一个实例,就是这样。 这不会导致您的类第二次加载。 由于您的课程未再次加载,因此不会重复此过程。 如果你将它声明为非静态属性,那么这是一个完全不同的故事。 考虑一下 - public class stack { stack obj = new stack(); ........ } 该声明相当于 - public class stack { ... -
为什么堆栈溢出?(Why does the stack overflow?)[2022-10-07]
因为即使在具有大量可用虚拟内存的现代系统上,调用堆栈的最大大小通常也被故意限制为1MB。 这通常不是一个基本限制; 可以修改它(在Linux中使用例如setrlimit() ,或者在Java中使用-Xss标志 )。 但需要这样做通常表示程序异常; 如果你有大型数据集,它们通常应该存储在堆上。 Because even on modern systems with lots of virtual memory available, the maximum size of the call stack is u ... -
Lua Stack溢出(Lua Stack Overflow)[2023-03-15]
在标准Lua中,您可以使用lua_pop函数从Lua堆栈中删除项目。 有关此用法的提示,请参阅此答案 。 如果您反复调用代码,最简单的方法是在处理之前存储堆栈的高度,然后将其恢复: int top = lua_gettop(L); ... /* some processing involving the stack*/ lua_settop(L, top); 现在,我不知道如何在Kahlua实现这一目标。 但是在源代码中我看到LuaCallFrame.getTop()和LuaCallFrame.setTo ... -
EBP是当前堆栈帧的基指针。 一旦用新值覆盖该基指针,对堆栈上项目的后续引用将不会引用堆栈的实际地址,而是引用刚刚提供的覆盖地址。 程序的进一步行为取决于堆栈随后是否以及如何在代码中使用。 EBP is the base pointer for the current stack frame. Once you overwrite that base pointer with a new value, subsequent references to items on the stack will refe ...
-
我不知道该怎么做,但是。 .. 如果你看看这个答案: jQueryUI:我如何自定义格式化Autocomplete插件结果? 你可以看到有一种方法可以摆弄jQuery的渲染逻辑来改变菜单项的显示方式。 还有一个名为renderMenu的内部jQuery函数,它实际上提供了选择。 我没试过这个,但我想通过打开那个黑盒子,并且替换或重新调整renderMenu及其相关功能,你就可以做你想要的 - 在实际的文本框中只渲染一个项目。 无论如何,这就是我要开始的地方。 编辑 我在jQuery UI中再次查看了自动填充 ...