素数环

把整数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; }

 

posted @ 2012-12-07 15:54  tsubasa_wp  阅读(207)  评论(0编辑  收藏  举报