给定1-n的一个排列,要求你将它们重排,使得任意两个相邻的数的和为质数。
一个正整数 n ( 1 <= n <= 20 )
输出一行一个1-n的排列,满足相邻的两个数相加为质数。
如果有多组解,输出字典序最小的那一个。
如果无解,输出-1。
2
1 2
3
1 2 3
回溯法
#include
#include
#define N 21
/*
* 独立集问题
* 回溯法
* 剑走偏锋,反正n才20,可以算出答案存到数组。
* 1
* 1 2
* 1 2 3
* 1 2 3 4
* 1 4 3 2 5
* 1 4 3 2 5 6
* 1 2 3 4 7 6 5
* 1 2 3 4 7 6 5 8
* 1 2 3 4 7 6 5 8 9
* 1 2 3 4 7 6 5 8 9 10
* 1 2 3 4 7 10 9 8 5 6 11
* 1 2 3 4 7 6 5 12 11 8 9 10
* 1 2 3 4 7 6 5 12 11 8 9 10 13
* 1 2 3 4 7 6 13 10 9 8 11 12 5 14
* 1 2 3 4 7 6 5 12 11 8 15 14 9 10 13
* 1 2 3 4 7 6 5 12 11 8 9 10 13 16 15 14
* 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11
* 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18
* 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18 19
* 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 19 18 11 20
*/
bool a[N][N];
bool b[N];
int stack[N];
int n;
bool flag = false;
bool isPrime(int num) {
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
void setAB() {
for (int i = 1; i < N; i++) {
for (int j = i; j < N; j++) {
a[i][j] = a[j][i] = isPrime(i + j);
}
b[i] = true;
}
}
void find(int i) {
for (int j = 1; j <= n; j++) {
if (a[stack[i - 1]][j] && b[j]) {
stack[i] = j;
b[j] = false;
if (i == n) {
flag = true;
return;
}
find(i + 1);
if (flag) {
return;
}
else { // 回退
b[j] = true;
}
}
}
}
int main()
{
std::cin >> n;
if (n <= 1) {
std::cout << (n==1)?1:-1;
return 0;
}
setAB();
stack[1] = 1;
b[1] = false;
find(2);
if (flag) {
for (int i = 1; i <= n; i++) {
std::cout << stack[i] << ' ';
}
}
else {
std::cout << -1;
}
}
读表法
#include
/*
* 独立集问题
* 回溯法
* 剑走偏锋,反正n才20,可以算出答案存到数组。
* 1
* 1 2
* 1 2 3
* 1 2 3 4
* 1 4 3 2 5
* 1 4 3 2 5 6
* 1 2 3 4 7 6 5
* 1 2 3 4 7 6 5 8
* 1 2 3 4 7 6 5 8 9
* 1 2 3 4 7 6 5 8 9 10
* 1 2 3 4 7 10 9 8 5 6 11
* 1 2 3 4 7 6 5 12 11 8 9 10
* 1 2 3 4 7 6 5 12 11 8 9 10 13
* 1 2 3 4 7 6 13 10 9 8 11 12 5 14
* 1 2 3 4 7 6 5 12 11 8 15 14 9 10 13
* 1 2 3 4 7 6 5 12 11 8 9 10 13 16 15 14
* 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11
* 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18
* 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18 19
* 1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 19 18 11 20
*/
int main()
{
int n;
scanf("%d", &n);
if (n < 1) {
printf("-1");
return 0;
}
char s[21][51] = { "0",
"1",
"1 2",
"1 2 3",
"1 2 3 4",
"1 4 3 2 5",
"1 4 3 2 5 6",
"1 2 3 4 7 6 5",
"1 2 3 4 7 6 5 8",
"1 2 3 4 7 6 5 8 9",
"1 2 3 4 7 6 5 8 9 10",
"1 2 3 4 7 10 9 8 5 6 11",
"1 2 3 4 7 6 5 12 11 8 9 10",
"1 2 3 4 7 6 5 12 11 8 9 10 13",
"1 2 3 4 7 6 13 10 9 8 11 12 5 14",
"1 2 3 4 7 6 5 12 11 8 15 14 9 10 13",
"1 2 3 4 7 6 5 12 11 8 9 10 13 16 15 14",
"1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11",
"1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18",
"1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18 19",
"1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 19 18 11 20"
};
printf("%s", s[n]);
}