uva 11212,11212
迭代加深搜尋
自己看的時候第一遍更本就看不懂。。是很水,但智商捉急也是沒有辦法的事情。
好在有幾個同學已經是做過了這道題並且對迭代加深搜尋的思路有了一定的瞭解,所以在某些不理解的地方詢問了一下他們的見解,
真的是很有協助,也許自己想要想很久才能想明白,還會很痛苦,稍微問一下別人的想法,點上一個方向,剩下的自己就能想得明白了。
迭代加深。
把answer(需要的步數或其他)在主函數裡面從零往上遞加,此之謂 “層數”,亦可謂之“深度”。用書上的話就是:
從小到大枚舉深度上限maxd,每次只考慮深度不超過maxd的節點。
對於可以使用回溯法求解,但是解答樹的深度沒有明顯上限的題目,可以考慮使用迭代加深搜尋。
設深度上的上限為maxd(或是設成lim),當前結點n的深度為dep,需要一個樂觀估價函數,此函數的作用判斷有沒有繼續dfs下去的必要:
如果在理想樂觀狀況下,此結點往下dfs都不能達到最終目標要求,則果斷需要剪枝。
(媽蛋就是幹啊,寫到這個地方發現自己的思路有點不清晰,可能有漏洞就回頭去研究了一下代碼,然後就哭了……自己原來根本沒有理解透徹,需要來理清楚~所以又用掉了好長的時間來搞明白某一步是用來幹神馬的,真是很二。。。)
對於下面這個代碼來講,我迷亂的地方在於每次都是重新遞迴還是就繼續了原來的狀態遞迴。。我一直以為是延續了原來的狀態(當然之前還有其他的理解誤區……太水了我當時跟本就完全沒弄明白啊),但是我發現我想不通,然後一陣狂想,最後還是想不通。。然後就鬱悶的從D區回到了宿舍。。然後洗漱之後開始和某小朋友溝通交流了一些事情,某小朋友還是太懂事了搞得自己不開心了,真是笨。。
咳咳扯偏了,,
然後我在某小朋友趕我去睡覺之後,偷偷找來代碼看了一眼,然後加了如下一組輸出判斷自己認知上是否有錯誤,然後特麼果然是有錯誤。。。人家本就是每次重新遍曆,根本沒有延續狀態。。那個類裡面的內容我將其誤當做全域變數真是要死啊。。
好吧那幾行全是一樣的輸出。。
然後一切問題就算是解決完了,把代碼就給出如下。。
臥槽還是很蛋疼這個理解誤區,這尼瑪太水了吧。。菜鳥果然是菜鳥哦,不知道啥時候能進化。。。。。
#include <iostream>#include <cstdio>#include <cstring>using namespace std;class Board{public: int a[16]; int h; int n; bool readIn() { int i; scanf("%d",&n); if (n == 0) return false; for (i=0; i<n; i++) { scanf("%d",a+i); } return true; } void printOut() { int i; for (i=0; i<n; i++) { printf("%d ", a[i]); } printf("\n"); printf("h=%d\n",h); } void move(int s,int e,int p) { int t[16],i,j; if (p < s) { for (i=0; i<p; i++) { t[i]=a[i]; } for (j=s; j<=e; j++,i++) { t[i]=a[j]; } for (j=p; j<s; j++,i++) { t[i]=a[j]; } for (j=e+1; j<n; j++,i++) { t[i]=a[j]; } } else { for (i=0; i<s; i++) { t[i]=a[i]; } for (j=e+1; j<p; j++,i++) { t[i]=a[j]; } for (j=s; j<=e; j++,i++) { t[i]=a[j]; } for (j=p; j<n; j++,i++) { t[i]=a[j]; } } memcpy(a,t,sizeof(t)); } int getH() { int cnt,i; cnt=0; for (i=0; i<n-1; i++) { if (a[i+1] != a[i]+1) cnt++; } if (a[i] != n) cnt++; h=cnt; return cnt; }};int lim;int f(int dep,int h){ return dep*3+h;}bool IDDFS(int dep,Board b){ int i,j,k; Board tb; b.getH(); if (f(dep,b.h) > lim*3) return false; if (b.getH() == 0) return true; for (i=0; i<b.n; i++) { for (j=i; j<b.n; j++) { for (k=0; k<i; k++) { tb=b; tb.move(i,j,k); if (IDDFS(dep+1,tb) == true) return true; } for (k=j+2; k<b.n; k++) { tb=b; tb.move(i,j,k); if (IDDFS(dep+1,tb) == true) return true; } } } return false;}int main(){ Board b; int prob; prob=1; while (b.readIn() == true) { for (lim=0; ; lim++) { for(int i=0;i<b.n;i++) printf("%d ",b.a[i]); printf("\n"); if (IDDFS(0,b) == true) break; } printf("Case %d: %d\n",prob,lim); prob++; }}用類寫的結構體,說真的我還沒用過。。看完某些題目和某些大神打完WF的感言之後現在都覺得自己寫的這叫什麼玩意吧==真是沒什麼難度了,也沒啥不好學的。這叫演算法麼,會這些應該是理所應當的事情吧,不練ACM估計也能會。。就是操蛋,以後好好乾,早點變大神不要再當大水筆了。。