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; }