1. 程式人生 > >素數環 dfs+回溯

素數環 dfs+回溯

題意:給定一個整數,求其滿足起點為1的素數環,,並把所有的素數環輸出來。

型別:dfs+回溯

思路:因為起點為1,所以每次都從1開始進行深度優先搜尋,設定一個數組ring,用來存放素數環的路徑,當找到素數環的時候就列印環的路徑。其中有一個剪枝的操作,如果給定的整數為奇數,那麼肯定不存在素數環,(因為肯定存在兩個奇數相鄰,而奇數與奇數的和為偶數,所以一定不是素數環)所以不用進行搜尋。做題的時候忘記寫輸入的資料以EOF結束,導致出現了Output Limit Exceeded這種錯誤。

時間複雜度:最壞的時間複雜度為O((n-1)!);

#include <iostream>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
int visit[30];//標記已被訪問的數 
int ring[30];//儲存環路徑 
int n;//節點個數 
 
 //判斷是否是素數 
bool isPrime (int a){
	int f=1;
	if(a==2){
		return f;
	}
	for(int i=2;i*i<=a;i++){
		if(a%i==0){
			f=0;
			break;
		}
	}
    return f;
}
 //dfs
 void dfs(int i){
 	if(i==n&&isPrime(ring[n]+1)){//滿足條件 則返回 
 		//列印路徑
		for(int j=1;j<=n;j++){
			cout<<ring[j]<<" ";
		} 
		cout<<endl; 
 		return ;
	 }
 	for(int j=2;j<=n;j++){
 		if(!visit[j]&&isPrime(ring[i]+j)){//沒有被訪問 並且與上次節點和為素數 
 			visit[j] = 1;//標記被訪問
 			ring[i+1] = j;
			dfs(i+1);
			visit[j] = 0;//回溯後  將節點置為未被訪問  下次要用 
		 }
	 } 	
 }

int main() {
    cin>>n;
    for(int i=1;i<=n;i++){//置所有節點未被訪問 
    	visit[i] = 0;
	}
	ring[1] = 1;//固定 1 為路徑第一個數 
	if(n%2!=0){//如果是奇數 無解 
		cout<<-1;
		return 0;
	}
	dfs(1);	
	return 0;
}