相鄰兩數和爲質數的排列

Description

給定一個數n,要求對 [1,n]裏面的整數重排序,使得相鄰的兩數和爲質數,若能且有多個結果輸出按字典序排列的第一個,若不能實現輸出-1 。spa

Input and Output

示例 1:code

輸入:3 輸出:1 2 3排序

示例 2:遞歸

輸入:5 輸出:1 4 3 2 5ip

Solution

  • 思路:   用dfs例舉全部組合,判斷是否知足條件。   如何例舉全部組合?參考領釦的全排列那題(cur位置元素和cur後面元素一一交換)io

  • 剪枝:   不是等排列完成了才判斷是否知足,而是交換一個次就判斷一次。cur位置前面是已排的,cur位置後是未排的。每當cur位置元素和後面元素交換時,就判斷cur位置和cur-1位置元素和是否是質數,若不是那麼這個方案就不用再繼續下去了。class

  • dfs中止:   一旦出現結果,整個遞歸所有結束,因此調用dfs前要錢判斷是否已獲得結果集合

  • 縮短判斷是否爲質數時間   把全部質數放到集合中,要判斷就到集合中找,而不須要依據公式在計算一遍di

#include <stdio.h>
#include <vector>
#include <set>
std::set<int> zhishus;//質數集 
std::vector<int> result;

int iszhishu(int num) {
//檢查num是否爲質數 
	if(num<=0) return 0;
	int i;
	for(i=2; i*i<=num; i++) {
		if(num%i==0) return 0;
	}
	return 1;
}

void dfs(std::vector<int> nums, int cur){
//全排列
	if(cur==nums.size()) {
		result=nums;
		return;
	}
	int i;
	for(i=cur; i<nums.size(); i++){
		std::swap(nums[cur],nums[i]);
		if( result.empty() && (cur==0 || zhishus.count(nums[cur]+nums[cur-1]) ) ) dfs(nums, cur+1);
		std::swap(nums[cur],nums[i]);
	}
}

int main() {
	int n,i,j;
	scanf("%d",&n);
	if(n<5) {
		for(i=1; i<=n; i++)  printf("%d ",i);
		return 0;
	}
	
	//構造質數集
	for(i=1; i<=n+n; i++) if(iszhishu(i)) zhishus.insert(i); 
	
	//構造 1~n
	std::vector<int> nums;
	for(i=1; i<=n; i++) nums.push_back(i);
	
	//全排列
	dfs(nums,0);
	
	if(result.empty()) printf("-1");
	else for(i=0; i<result.size(); i++)  printf("%d ",result[i]);
	return 0;
	
}
相關文章
相關標籤/搜索