描述
把1到20这重新排列,使得排列后的序列A满足:
a. 任意相邻两个数之和是素数
b. 不存在满足条件a的序列B使得:A和B的前k(0 <= k <=
19)项相同且B的第k+1项比A的第k+1项小。(即按字典序排列的第一项)
输入
没有输入。
输出
输出A,两个数字之间用一个空格隔开,第一个数字前面和最后一个数字后面没有空格。
答案是
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 20 11 12 19 18
直接看程序
#include <iostream>
using namespace std;
int index[20]; //最后要打印的表,一个格子存放1-20中的一个数字
int used[21] = { 0 }; //数字是否使用过
int N = 20; //素数环大小,题目为20
int isPrime(int n); //判断一个数是否为素数
void nfind(int m); //找到第index[m]应该是哪一个数
int main() {
index[0] = 1; //初始化第一个数为1
nfind(1); //从index[1]找数
return 0;
}
void nfind(int m) {
int i;
if (m == N && isPrime(index[0] + index[N - 1])) {
//如果找到index[N - 1] 且 首尾判断有效
for (i = 0; i < N - 1; i++) {
cout << index[i] << ' ';
}
cout << index[N - 1] << endl;
exit(0); //打印并直接退出
}
for (i = 2; i <= N; i++) {
index[m] = i; //从2~N中挑选一个数i放到index[m]中
if (isPrime(index[m] + index[m - 1]) && used[i] == 0) {
//如果前后两数相加为素数 且 i没有被使用过
used[i] = 1;
nfind(m + 1); //使用i,并搜索index[m+1]
used[i] = 0; //不使用i,返回上一层
}
}
return;
}
int isPrime(int n) {
int i;
for (i = 2; i < n; i++) { //这里用sqrt(n)更好,但是我不想调用math.h了
if (!(n % i)) {
return 0;
}
}
return 1;
}
再上个没有注释的版本:
#include <iostream>
using namespace std;
int index[20];
int used[21] = {0};
int N = 20;
int isPrime(int n);
void nfind(int m);
int main() {
index[0] = 1;
nfind(1);
return 0;
}
void nfind(int m) {
int i;
if (m == N && isPrime(index[0] + index[N - 1])) {
for (i = 0; i < N - 1; i++) {
cout << index[i] << ' ';
}
cout << index[N - 1] << endl;
exit(0);
}
for (i = 2; i <= N; i++) {
index[m] = i;
if (isPrime(index[m] + index[m - 1]) && used[i] == 0) {
used[i] = 1;
nfind(m + 1);
used[i] = 0;
}
}
return;
}
int isPrime(int n) {
int i;
for (i = 2; i < n; i++) {
if (!(n % i)) {
return 0;
}
}
return 1;
}