[問題] knight漫遊 用遞迴解

看板C_and_CPP作者 (東方一隻鹿)時間15年前 (2010/08/11 19:20), 編輯推噓8(809)
留言17則, 7人參與, 最新討論串1/1
( *[1m *[m 為色碼,可以按 Ctrl+V 預覽會顯示的顏色 ) ( 未必需要依照此格式,文章條理清楚即可 ) 遇到的問題: (題意請描述清楚) 不知道想要問什麼了 堆疊解還OK 遞迴就很難弄-.- 而且偏偏一堆書都扯什麼遞迴不值得用啦 用其他方法解安定 SO只好來這貼CODE了 希望得到的正確結果: 輸出會跑出5*5棋盤 從(1,1)這個起點開始 然後1234567...標到24一次走完 不用回到原點 程式跑出來的錯誤結果: 堆疊的話 是利用回朔法 就可以返回去重走 但遞迴也真的沒啥經驗(只有階乘和河內塔) 大概講一下我那程式怎麼用遞迴 1.我嘗試用遞迴 返回去 2.最後一次的遞迴 = 已經是確定常數的回傳值 3.大概是跑無限遞迴吧 最終是記憶體XXX錯誤 用pause測圖時是還可以畫 4.問題的癥結點 到跑第20個位子後 騎士已經無法可走 要逆回的時候 其實一開始想是 不要逆回了 找個方法讓這個遞迴暴掉 讓上一個遞迴可以去跑 但不知道該怎麼做-.- 如果真的有這個方法就先講這部分吧.... 5.這是一個問題啦 遞迴是不是 只要執行到回傳固定的值 之前的一堆遞迴就暴掉了 是嗎? 開發平台: (例: VC++ or gcc/g++ or Dev-C++, Windows or Linux) devc++ 有問題的code: (請善用置底文標色功能) #include <stdio.h> #include <stdlib.h> #define MAXSIZE 10 #define SUCCESS 1 #define FAILURE 0 #define EMPTY -1 int board[MAXSIZE+1][MAXSIZE+1]; int n; //working board size int offset_x[] = {2,1,-1,-2,-2,-1,1,2}; int offset_y[] = {1,2,2,1,-1,-2,-2,-1}; int count=0; void initial(int); void display(); int move(int,int,int,int); void show(); int main() { n=5; initial(n); show(); system("pause"); } void initial(int n) { int i,j; /*棋盤初始化*/ for(i=1;i<=n;i++) for(j=1;j<=n;j++) board[i][j]=EMPTY; printf("====在%d*%d的西洋棋盤上====\n",n,n); } void show() { if(move(1,1,-1,-1) == FAILURE) //起點從(1,1)開始 printf("NO SOLUTION\n"); else display(); } #define YES 1 #define NO 0 #define BOARD(x,y) (1<=x) && (x<=n) && (1<=y) && (y<=n) #define CHECK(x,y) board[x][y] == EMPTY int move(int x, int y,int visited,int ignore) { int new_x,new_y,i=0,j,found=NO; //已設 board[1][1]=0; while(count < n*n-1){ found = NO; while (i < 8){ //八個方向都試 if(i==visited && ignore==YES) i++; ignore = NO; new_x = x + offset_x[i]; new_y = y + offset_y[i]; if(BOARD(new_x,new_y) && CHECK(new_x,new_y)){ board[new_x][new_y]=++count; found = YES; ignore = NO; visited = i; move(new_x,new_y,visited,ignore); break; } else i++; } /*八個方向都不能走*/ if(!found) // cout<<(!found) 輸出是0 if(count > 0){ board[x][y] = EMPTY ; new_x = x - offset_x[visited]; new_y = y - offset_y[visited]; count--; ignore=YES; return move(new_x,new_y,visited,ignore); } else return FAILURE; } return SUCCESS; } 補充說明: display()函式沒問題我就不寫了 精華區的看過了 那是用堆疊 先吃個飯 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 118.171.74.174

08/11 19:22, , 1F
你再仔細想想看你所謂的"遞迴爆掉"是什麼意思
08/11 19:22, 1F

08/11 19:22, , 2F
(我是指 4. 裡說的那個)
08/11 19:22, 2F

08/11 19:23, , 3F
想成讓這一次遞迴「告訴」上一層說我這裡死掉了這種感覺
08/11 19:23, 3F

08/11 19:23, , 4F
這樣你就會寫了
08/11 19:23, 4F

08/11 19:41, , 5F
請問.....什麼叫做堆疊解?
08/11 19:41, 5F

08/11 19:43, , 6F
其實,只要讓遞回的方法返回true或 flase就好了
08/11 19:43, 6F

08/11 19:44, , 7F
應該是用stack來解的意思吧
08/11 19:44, 7F

08/11 19:48, , 8F
遞迴也是堆疊啊 0.0
08/11 19:48, 8F
ture false不是相當於1 0嗎 不過先試試看好了.. 另外堆疊解是指用top什麼的去指一個資料結構

08/11 19:50, , 9F
請問題目長什麼樣子? 有點想玩玩看.....
08/11 19:50, 9F

08/11 19:51, , 11F
是這個嗎?
08/11 19:51, 11F
Y 目前這題目是類似的 ※ 編輯: calqlus 來自: 118.171.74.174 (08/11 20:04) 意外的成功了= = 我取消ignore的引入值 把八個方向找不到的那個函式 回傳值 改 false 就瞬殺了..... 感謝PTT良解 ※ 編輯: calqlus 來自: 118.171.74.174 (08/11 20:09) 剛剛又發現一件不幸的事 他移動的位子 11->12 出錯了.. 不過改一下應該就好了 ※ 編輯: calqlus 來自: 118.171.74.174 (08/11 20:11) if(i==vi) i++那段下一行 補if(i>=8) break; GG ※ 編輯: calqlus 來自: 118.171.74.174 (08/11 20:13)

08/11 20:28, , 12F
如果您不採用回傳判斷,而是reference或global variable
08/11 20:28, 12F

08/11 20:29, , 13F
可以不必count--。
08/11 20:29, 13F

08/11 21:08, , 14F
具體程式碼 http://nopa.csie.org/5e068 跑8就要1x秒。
08/11 21:08, 14F

08/11 21:48, , 15F
遞迴解的好處是比較不用動腦想一組一致的控制規則,而是
08/11 21:48, 15F

08/11 21:49, , 16F
用一點簡單的規則,放出去,讓程式自己試,試錯了就中斷那支.
08/11 21:49, 16F

08/12 00:38, , 17F
這我寫過XD 還記得課本演算法不是最佳解 只是近似 要偷吃!
08/12 00:38, 17F
文章代碼(AID): #1COeTa-x (C_and_CPP)