一道经典的算法题。链接:https://onlinejudge.org/external/5/524.pdf。
这里的原题的描述,我们需要注意的只有输入和输出的格式那里,对于题意的理解,书中的中文描述已经足够了,因为题意是比较简单的。(这里可以去书上读一下题目的意思。)
首先,素数的定义:wiki。
大于 1 的自然数中,除了 1 和该数自身外,无法被其他自然数整除的数。(2 当然是素数。)
关于输出中的数字排列的顺序,书上说是逆时针排列,而原题中说的是顺时针和逆时针,这个其实无所谓,我们依次 dfs 过去,最终会把顺时针和逆时针的情况全部囊括的。
然后,书上首先介绍了一个“生成-测试”法,这个比较容易,这里就不去详细说明,我们就简单看下用到的 next_permutation
这个函数,可以看一下文档。
核心的部分是这个 dfs,
1/*
2 从 1 开始,依次去搜索每个位置上的可能性
3
4 cur: 当前的位置
5*/
6void dfs(int cur) {
7 if (cur == n && isp[A[0] + A[n - 1]]) { // 递归边界
8 for (int i = 0; i < n; i++) {
9 if (i != 0)
10 printf(" ");
11 printf("%d", A[i]);
12 }
13 printf("\n");
14 } else
15 for (int i = 2; i <= n; i++)
16 if (!vis[i] && isp[i + A[cur - 1]]) { // 判断当前的数字是否可行,不行的就跳过,相当于是剪枝了
17 A[cur] = i;
18 vis[i] = 1; // 标记已经访问过
19 dfs(cur + 1); // 递归处理下一个位置
20 vis[i] = 0; // 还原
21 }
22}
我们直接看所有的代码,一次性整体进行讲解。