素数环
把整数1,2,3...n组成一个环, 相邻两环之和为素数, 每种环输出一次.
1. 穷举所有排列. 排列总数为n!个.当n取17时, 运算结果如下:
total: 0. with running time: 3.994225 sec.
已经有些吃力了Orz...
(代码有点啰嗦, 这里可以直接使用next_permutation()来实现)
额..后来发现这个属于回溯.
#define S 17
int total = 0;
int N[S] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
int C[S] = {0};
bool isPrime(int n) {
for ( int i = 2; i < n; i++)
if ( n%i == 0 ) return false;
return true;
}
void subset(int n, int *a, int cur) {
if ( n == cur ) {
//for ( int i = 0; i < n; i++ ) printf("%d ", C[i]); printf("\n");
total ++;
return;
}
for ( int i = 0; i < n; i++ ) {
int ok = 1;
for ( int j = 0; j < cur; j++ ) {
if ( C[j] == N[i] ) { ok = 0; break; }
}
if ( !ok ) continue;
if ( cur ) if ( !isPrime( C[cur - 1] + N[i]) ) ok = 0;
if ( cur == n - 1 ) if ( !isPrime( C[0] + N[i]) ) ok = 0;
if ( ok ) {
C[cur] = N[i];
subset(n, a, cur + 1);
}
}
}
int main() {
C[0] = 1;
clock_t t0 = clock();
subset(S, C, 1);
clock_t t1 = clock();
printf("total: %d. with running time: %f sec.\n", total, ((float)(t1-t0))/CLOCKS_PER_SEC);
return 0;
}
使用STL的版本:
代码少了很多, 但这个版本n>12就算不出来了Orz..
int main() {
int n = S;
int isp[S*2+1] = {0};
int A[S];
for ( int i = 2; i < S*2; i++ ) isp[i] = isPrime(i);
clock_t t0 = clock();
for ( int i = 0; i < n; i++ ) A[i] = i+1;
do {
int ok = 1;
for ( int i = 0; i < n; i++ ) if ( !isp[A[i]+A[(i+1)%n]] ) { ok = 0; break;}
if ( ok ) {
total ++;
}
} while (next_permutation(A+1, A+n));
clock_t t1 = clock();
printf("total: %d. with running time: %f sec.\n", total, ((float)(t1-t0))/CLOCKS_PER_SEC);
return 0;
}
2. 回溯法.
这是最快的版本. n=16只需0.1s.
注意素数要用素数表保存.
void dfs(int cur) {
if ( n == cur && isPrime(C[0] + C[n-1])) {
total++;
return;
}
for ( int i = 2; i <= n; i++ ) {
if ( !vis[i] && isp[i+C[cur-1]] ) {
vis[i] = 1;
C[cur] = i;
dfs(cur + 1);
vis[i] = 0; // 重要! 清除标志.
}
}
}
int main() {
for ( int i = 2; i < S*2; i++ ) isp[i] = isPrime(i);
C[0] = 1;
vis[1] = 1;
dfs(1);
return 0;
}

浙公网安备 33010602011771号