质数环,一道ACM题,使用了回溯+DFS
题目描述
A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime.
Note: the number of first circle should always be 1.
输入
n (0 < n < 20).
(multi test case)
输出
The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order.
You are to write a program that completes above process.
Print a blank line after each case.
样例输入
6
8
样例输出
Case 1:
1 4 3 2 5 6
1 6 5 2 3 4
Case 2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2
分析
如果符合条件,放入进行后续DFS尝试,若失败则取出,尝试其他可能。
经典的回溯思想。
#include <bits/stdc++.h>
using namespace std;
vector<int> ans;
int n;
int visited[20];
int l = 1;
int isPrime(int num){
//判断是否为质数
for(int i = 2;i<num/2+1;i++)
if(num%i == 0)
return 0;
return 1;
}
void traceback(int now,int num){
//回溯+DFS
if(now > num&&isPrime(ans.back()+1)){
//最后一个的判断,因为是环,要首尾相加判断
for(int i = 0;i<num-1;i++)
cout<<ans[i]<<" ";
cout<<ans[num-1]<<endl;
return;
}
for(int i = 1;i<=num;i++){
if(!visited[i]&&isPrime(ans.back()+i))
{
//如果没有visit过且与前项相加为质数,则放入
ans.push_back(i);
visited[i] = 1;
traceback(now+1,num);
//取出,回溯过程
visited[i] = 0;
ans.pop_back();
}
}
}
int main()
{
while(cin>>n){
ans.clear();
ans.push_back(1);
memset(visited,0,sizeof(visited));//全置为0
visited[1] = 1;
cout<<"Case "<<l<<":"<<endl;
traceback(2,n);
cout<<endl;
l++;
}
}