[DFS]排隊(間隔排列)-C++

Description

小Q是班長。在校運動會上,小Q班要進行隊列表演。小Q要選出2*N名同窗編隊,每人都被編上一個號,每個從1到N的天然數都被某2名同窗佩戴,如今要求將他們排成一列,使兩個編號爲1的同窗中間剛好夾1名同窗,兩個編號爲2的同窗中間剛好夾2名同窗,……,兩個編號爲N的同窗中間剛好夾N名同窗,小Q但願知道這樣的排法可否實現。c++

Input

輸入文件僅包括一行,即要處理的N。N<=13優化

Output

輸出有多少種排列順序.spa

Sample Input

3code

Sample Output

2blog

先理解一下題目,題目中所述,每個從1到N的天然數都被某2名同窗佩戴,說明共有2N名同窗,兩個編號爲N的同窗中間剛好夾N名同窗,就能夠獲得一個排列(以n==3爲例):隊列

在這裏插入圖片描述
而後,就能夠用DFS搜索了。圖片

#include<bits/stdc++.h>
using namespace std;

int n,ans=0;
int flag[100]={0};

void dfs(int dep){
	
	if(dep>n){
		ans++;
		return ;
	}
	for(int i=1;i<=2*n-dep-1;i++){
		if(!flag[i]&&!flag[i+dep+1]){//考慮當前位置有無其餘數,和它的間隔有沒有其餘數
			flag[i]=flag[i+dep+1]=1;
			dfs(dep+1);
			flag[i]=flag[i+dep+1]=0;
		}
	}
}
int main(){
	cin >> n;
	dfs(1);
	cout << ans;
	
	return 0;
}

可是,能夠發現,當程序運行12或13時,耗時很長,那麼就能夠想到剪枝優化。ip

if(n%4==1||n%4==2){
		return ; 
	}

如今,就能夠證實一下這個剪枝的獲得。
設問題的一個解爲a1+a2···+an,a1表示1。
那麼能夠獲得a1+a2+…+an+(a1+1+1)+(a2+2+1)+…+(an+n+1),最後解得4(a1+a2+…+an)=n(3n-1),因此n%41或n%42無解。ci

#include<bits/stdc++.h>
using namespace std;

int n,ans=0;
int flag[100]={0};

void dfs(int dep){
	
	if(n%4==1||n%4==2){
		return ; 
	}
	if(dep>n){
		ans++;
		return ;
	}
	for(int i=1;i<=2*n-dep-1;i++){
		if(!flag[i]&&!flag[i+dep+1]){
			flag[i]=flag[i+dep+1]=1;
			dfs(dep+1);
			flag[i]=flag[i+dep+1]=0;
		}
	}
}
int main(){
	cin >> n;
	dfs(1);
	cout << ans;
	
	return 0;
}
相關文章
相關標籤/搜索