題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1016
題目大意:
一道關於求素數環的問題,輸入一個數字n,按字典序輸出從1到n的所有可以連成素數環串。
解題思路:
素數環的定義是將從1到n這n個整數圍成一個圓環,若其中任意2個相鄰的數字相加,結果均爲素數,那麼這個環就成爲素數環。例如:當n爲10時,序列:1 2 3 8 5 6 7 10 9 4 就可以形成一個素數環。
素數環的生成可以用深搜來實現,素數用素數篩來打表,再用一個布爾型數組來記錄一個數字是否被訪問過。需要注意的是標記數字的回溯和首尾的數字和也應爲素數,然後控制格式輸出就可以了。
代碼:
/*
ID: Code-Cola
PROG: 1016
LANG: C++
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
/********** 全局變量 **********/
int n;
int a[25]; //存儲生成的序列
bool k[25]; //記錄某個數字是否被訪問過
bool pk[40]; //素數判定
int p[12];
/********** 函數聲明 **********/
void dfs(int t); //搜索函數
void prime(); //素數篩
bool Is_prime(int x); //素數判定
int main()
{
int i = 1;
prime();
while (~scanf("%d",&n)) {
printf("Case %d:\n",i++);
memset(k, 1, sizeof(k)); //初始化爲true
a[0] = 1;
dfs(1); //進行深搜
cout << endl;
}
}
void dfs(int t)
{
int i;
if (t == n && Is_prime(a[n - 1] + a[0])) { //判斷首尾數字和
printf("%d",a[0]);
for (i = 1; i < n; i++) {
printf(" %d",a[i]); //控制格式輸出
}
printf("\n");
return;
}
for (i = 2; i <= n; i++) {
if (k[i] && Is_prime(i + a[t - 1])) {
a[t] = i;
k[i] = false;
dfs(t + 1); //遞歸
k[i] = true; //回溯
}
}
}
void prime() //素數篩
{
memset(pk, 0, sizeof(pk));
int i,j,num = 0;
p[num++] = 2;
pk[0] = pk[1] = pk[4] = true;
for (i = 3; i < 40; i += 2) {
if (!(pk[i]))
p[num++] = i;
for (j = 1; j < num && i * p[j] < 40; j++) {
pk[i * p[j]] = 1;
if (!(i % p[j]))
break;
}
}
}
bool Is_prime(int x)
{
return (x & 1) || x == 2 ? !pk[x] : false;
}