关于回溯和后宫
這是八皇后問題的升級(jí)版,主要是一個(gè)荒淫無道的國王娶的一堆皇后瓜分天下的故事。不清楚的同學(xué)請(qǐng)轉(zhuǎn)身百度,這里小子就不多說了。
回溯是我們玩迷宮游戲?qū)S玫囊环N思維模式。主要是先沿著一個(gè)方向走,若干步后若無法繼續(xù)走下一步,則退回一步,朝另一個(gè)方向探索,直到終點(diǎn)或返回起點(diǎn)。所以我們可以先從第一行左邊開始,一個(gè)一個(gè)的往下一行放置皇后,每放置一個(gè)皇后,判斷一次是否與之前所放置的皇后的領(lǐng)域有所沖突。
判斷項(xiàng)有三項(xiàng),分別是列、主對(duì)角線、副對(duì)角線。若是領(lǐng)域已被占領(lǐng),則判偽;若未被占領(lǐng),則判真。判真的情況下,該點(diǎn)即可作為其中一個(gè)可能的答案。讓我們來看一下如何去判斷領(lǐng)域是否沖突:
1.列的領(lǐng)域比較好判斷,就是一個(gè)數(shù)組,角標(biāo)和已放置的皇后的橫坐標(biāo)相同的,即標(biāo)記為1,表示已有皇后將此列占領(lǐng),未占領(lǐng)的即標(biāo)記為0。
2.主對(duì)角線較為復(fù)雜,我們先看下邊的圖:
不難得出,同一主對(duì)角線的橫縱坐標(biāo)的差是相同的,那么就將差值當(dāng)做判斷數(shù)組的角標(biāo),用1、0分別標(biāo)記已占領(lǐng)和未占領(lǐng),不過有些坐標(biāo)的差值會(huì)是負(fù)值,但數(shù)組的角標(biāo)不會(huì)是負(fù)值,所以為了防止這種情況,要為差值同一加上一個(gè)數(shù),以保證結(jié)果是正值。
3.副對(duì)角線的判斷方法也可從上圖推出,這里就交給同學(xué)們?nèi)ニ伎剂恕?/p>
以上就是該題的思考過程,代碼如下:
1 #include<stdio.h> 2 int n;//有n個(gè)皇后 3 int sum=0;//方法總數(shù) 4 int flag2[101]={0};//A對(duì)角線標(biāo) 5 int flag3[101]={0};//B對(duì)角線標(biāo) 6 int ans[9]={0};//放置坐標(biāo),角標(biāo)為x,數(shù)據(jù)為y 7 int flag1[9]={0};//列標(biāo) 8 void out();//該函數(shù)主要用于方法數(shù)統(tǒng)計(jì)與輸出結(jié)果 9 void search(int k);//用于回溯,從第k行開始放置 10 int main() 11 { 12 scanf("%d",&n); 13 search(1);//從第1行開始 14 return 0; 15 } 16 void search(int k) 17 { 18 int i; 19 for(i=1;i<=n;i++) 20 { 21 if( (!flag1[i]) && (flag2[i-k+10]==0) && (flag3[i+k]==0) ) 22 /*判斷語句第一節(jié)判斷這一列是否在之前皇后的領(lǐng)域中, 23 第二節(jié)判斷主對(duì)角線,第三節(jié)判斷副對(duì)角線*/ 24 { 25 ans[k]=i; 26 flag1[i]=1; 27 flag2[i-k+10]=1; 28 flag3[i+k]=1; 29 if(k==n) out();//若到邊界即達(dá)成一種情況 30 else search(k+1);//未到邊界則繼續(xù)探索 31 flag1[i]=0; 32 flag2[i-k+10]=0; 33 flag3[i+k]=0; 34 } 35 } 36 } 37 void out() 38 { 39 int i; 40 sum++; 41 printf("%d:\n",sum); 42 for(i=1;i<=n;i++) 43 printf("(%d,%d)\n",i,ans[i]); 44 }? 代碼如有錯(cuò)誤,歡迎指出,如果這篇博客給了讀者幫助,那是小子的榮幸。
轉(zhuǎn)載于:https://www.cnblogs.com/LegendLa/p/4515039.html
總結(jié)
- 上一篇: 一个类怎样引用另外一个类的成员变量或方法
- 下一篇: 07、poly-A内参和杂交内参(arr