1. 程式人生 > >搜尋&回溯——N皇后(hdu2553)

搜尋&回溯——N皇后(hdu2553)

題目連結:

題目描述:

在N*N的方格棋盤放置了N個皇后,使得它們不相互攻擊(即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。
你的任務是,對於給定的N,求出有多少種合法的放置方法。

解決思路:

回溯官方課題~用這道題理解回溯再合適不過了,下面的程式碼也是初學回溯時所寫的,感覺自己萌萌噠~

百科一下回溯法:

回溯演算法也叫試探法,它是一種系統地搜尋問題的解的方法。回溯演算法的基本思想是:從一條路往前走,能進則進,不能進則退回來,換一條路再試。用回溯演算法解決問題的一般步驟為:
1、定義一個解空間,它包含問題的解。
2、利用適於搜尋的方法組織解空間。
3、利用深度優先法搜尋解空間。
4、利用限界函式避免移動到不可能產生解的子空間。
問題的解空間通常是在搜尋問題的解的過程中動態產生的,這是回溯演算法的一個重要特性。

其實說白了 就是 遞迴前改變一個狀態,遞迴後再改回來~2333333   比如說

n++;

f(n)              //試探下一步

n--;

N皇后即,當前點可以放置皇后就試探性的放,當其所有子節點遍歷完之後再接著考慮後面的選擇

shu[i]=you[m+i]=zuo[m-i+n]=1;  //假設採取當前方案。 
hs(m+1);                       //走到下一行。 
shu[i]=you[m+i]=zuo[m-i+n]=0;  //執行完回溯還原。 

完整程式碼:

#include<stdio.h>
#include<string.h> 
int shu[110],zuo[110],you[110];      //記錄"上""左""右"狀態。 
int n,sum;
int x[11]={0,1,0,0,2,10,4,40,92,352,724};//N=1~10答案,測試資料。 

void hs(int m)//無剪枝完全回溯,對於每個可選擇路線都會走一遍,然後還原。
{
	int i;
	if(n<m)     //如果n<m了,即最後一行也走完了,sum++並返回。 
	{
	sum++;
	return;
    }
	for(i=1;i<=n;i++)   //回溯開始 
	{
		if(!shu[i]&&!you[m+i]&&!zuo[m-i+n]) //如果滿足三個條件為0(可選) 
//注意zuo,you陣列要是測試資料的2倍,左邊減到負值時要加個n即從最右開始。 
		{                                   
			shu[i]=you[m+i]=zuo[m-i+n]=1;  //假設採取當前方案。 
			hs(m+1);                       //走到下一行。 
			shu[i]=you[m+i]=zuo[m-i+n]=0;  //執行完回溯還原。 
		}
	}
} 

int a[11];

int main()
{
     int nn;
     for(n=1;n<=10;n++)          //打表 
     {
     memset(shu,0,sizeof(n));    //三個記錄狀態的陣列清零 
     memset(zuo,0,sizeof(n));
     memset(you,0,sizeof(n));
     	sum=0;
     	hs(1);                   //從第一行開始 
	    a[n]=sum;                //結果存在a數組裡 
     }
		 
		            
     while(~scanf("%d",&nn)&&nn)
     {
        printf("%d\n",a[nn]);
     }
}