题目:http://codevs.cn/problem/1031/
思路: 为了简化深度搜索的次数,首先计算17+16=33以内的所有质数,然后计算整数x后续的所有可能数next,使用深度搜索来计算质数环。
题解:
/* 1031 质数环 */
#include <stdio.h>
#define MAXN 18
int n; /* 质数环大小 */
int next[MAXN][MAXN]; /* 后续数字备选数组 */
int nextn[MAXN]; /* 后续数字备选数量 */
int prime[MAXN]; /* 所有质数值 */
int primen; /* 所有质数数量 */
int cycle[MAXN]; /* 质数环 */
int used[MAXN]; /* 是否已在环中 */
/* 判断是否为质数 */
int is_prime(int x)
{
int i;
if(x == 2)
{
return 0;
}
for(i = 2; i * i <= x; i++)
{
if(0 == x % i)
{
return 0;
}
}
return 1;
}
/* 获取后续值 */
void get_next()
{
int i, j;
int d;
for(i = 1; i <= n; i++)
{
nextn[i] = 0;
for(j = 0; j < primen; j++)
{
d = prime[j] - i;
if(d > 0 && d <= n)
{
next[i][nextn[i]] = d;
nextn[i]++;
}
}
}
}
/* 求质数环 */
void dfs(int depth, int x)
{
int i, nextx;
if(depth > n)
{
/* 后续有值可组成质数,且第一个值为1 */
if(nextn[x] > 0 && next[x][0] == 1)
{
for(i = 1; i < depth; i++)
{
printf("%d ",cycle[i]);
}
printf("\n");
}
}
else
{
/* 遍历后续可能的值 */
for(i = 0; i < nextn[x]; i++)
{
nextx = next[x][i];
/* 如果值未在环中,继续深度搜索 */
if(0 == used[nextx])
{
used[nextx] = 1;
cycle[depth] = nextx;
dfs(depth + 1, nextx);
used[nextx] = 0;
}
}
}
}
/* 主函数入口 */
int main()
{
int i; /* 索引值 */
scanf("%d", &n);
/* 计算所有质数 */
primen = 0;
for(i = 1; i < MAXN * 2; i++)
{
if(1 == is_prime(i))
{
prime[primen] = i;
primen++;
}
}
/* 测试 - 打印所有质数 */
/*
printf("%d: ", primen);
for(i = 0; i < primen; i++)
{
printf("%d ", prime[i]);
}
printf("\n");
*/
/**********************/
/* 获取后序质数 */
get_next();
/* 测试 - 打印后续质数 */
/*
for(i = 1; i <= n; i++)
{
printf("%d: ", i);
for(j = 0; j < nextn[i]; j++)
{
printf("%d ", next[i][j]);
}
printf("\n");
}
*/
/**********************/
/* 初始化使用表 */
for(i = 1; i <= n; i++)
{
used[i] = 0;
}
used[1] = 1;
cycle[1] = 1;
dfs(2, 1);
return 0;
}