UVA524 UVALive5270 HDU1016 ZOJ1457 Prime Ring Problem【DFS】

Regionals 1996 >> Asia - Shanghai

问题链接UVa524 UVALive5270 HDU1016 ZOJ1457 Prime Ring Problem

问题简述:输入一个数n(0<n<20),用1到n的整数围成一个圈,使得相邻的两个数之和为素数,输出各种可能的圈。

本题可以使用深度优先搜索求解。程序中,函数dfs()的参数为已经有几个数满足相邻为素数,其功能是寻找下一个满足条件的数。

问题分析:因为是一个圈,并且用1到n的整数都要被用到,所以将1固定在一个位置上。这样做也可以减少重复的搜索。

程序说明

需要注意的是,HDU1016的格式与UVA524的格式略为不同,空行的位置不同。

对于HDU1016与UVA524,分别编写了一个根据快速简洁的C++的版本。


AC的C++语言程序如下(HDU1016,快速简洁版):

/* HDU1016 Prime Ring Problem */

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>

using namespace std;

#define N 20

int prime[N * 2];

int ans[N];
int visited[N];
int n, flag;

// Eratosthenes筛选法
void sieveofe(int p[], int n)
{
    int i, j;

    p[0] = 0;
    p[1] = 0;
    p[2] = 1;

    // 初始化
    for(i=3; i<n; i++) {
        p[i++] = 1;
        p[i] = 0;
    }
    int max = sqrt(n);
    for(i=3; i<=max; i++){
        if(p[i]) {
            for(j=i+i; j<=n; j+=i)    //进行筛选
                p[j]=0;
        }
    }
}

void print_result()
{
    int i;

    for(i=1; i<=n; i++) {
        if(i != 1)
            printf(" ");
        printf("%d", ans[i]);
    }
    printf("\n");
}

void dfs(int count)
{
    int i;

    if(count == n) {
        if(prime[ans[count] + ans[1]])
            print_result();     // 输出结果
    } else {
        for(i=2; i<=n; i++)
            if(!visited[i] && prime[i + ans[count]]) {
                ans[count + 1] = i;
                visited[i] = 1;
                dfs(count + 1);
                visited[i] = 0;
            }
    }
}

int main(void)
{
    sieveofe(prime, N * 2 -1);

    int caseno=0;

    while(scanf("%d", &n) != EOF) {
        // 初始化标志
        memset(visited, 0, sizeof(visited));

        printf("Case %d:\n",++caseno);

        // 深度优先搜索并且输出结果
        ans[1] = 1;
        visited[1] = 1;
        flag = 1;
        dfs(1);

        printf("\n");
    }

    return 0;
}

AC的C语言程序如下(HDU1016):

/* HDU1016 ZOJ1457 Prime Ring Problem */

#include <stdio.h>
#include <memory.h>
#include <math.h>

#define MAXN 20

int ans[MAXN];
int visit[MAXN];
int n, count;

// 试除法判断一个数是否为素数
int isprime(int n)
{
    if((n & 1) == 0)  // 偶数:n % 2 == 0
        return 0;

    if(n == 3)
        return 1;

    int end = sqrt(n), i;
    for(i=3; i<=end; i+=2) {
        if(n % i == 0)
            break;
    }

    return i > end ? 1 : 0;
}

void print_result()
{
    int i;

    for(i=1; i<=n; i++) {
        if(i != 1)
            printf(" ");
        printf("%d", ans[i]);
    }
    printf("\n");
}

void dfs(int count)
{
    int i;

    for(i=2; i<=n; i++)
        if(!visit[i]) {
            if(isprime(ans[count] + i)) {
                count++;
                if(count == n) {
                    if(isprime(i + ans[1])) {
                        ans[count] = i;
                        print_result();     // 输出结果
                    }
                } else {
                    ans[count] = i;
                    visit[i] = 1;
                    dfs(count);
                    visit[i] = 0;
                }
                count--;
            }
        }
}

int main(void)
{
    int caseno=0;

    while(scanf("%d", &n) != EOF) {
        // 初始化标志
        memset(visit, 0, sizeof(visit));

        printf("Case %d:\n",++caseno);

        // 深度优先搜索并且输出结果
        count = 1;
        ans[1] = 1;
        visit[1] = 1;
        dfs(count);

        printf("\n");
    }

    return 0;
}


AC的C++语言程序如下(UVA524,快速简洁版):

/* UVA524 UVAlive5270 Prime Ring Problem */

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>

using namespace std;

#define N 20

int prime[N * 2];

int ans[N];
int visited[N];
int n, flag;

// Eratosthenes筛选法
void sieveofe(int p[], int n)
{
    int i, j;

    p[0] = 0;
    p[1] = 0;
    p[2] = 1;

    // 初始化
    for(i=3; i<n; i++) {
        p[i++] = 1;
        p[i] = 0;
    }
    int max = sqrt(n);
    for(i=3; i<=max; i++){
        if(p[i]) {
            for(j=i+i; j<=n; j+=i)    //进行筛选
                p[j]=0;
        }
    }
}

void print_result()
{
    int i;

    for(i=1; i<=n; i++) {
        if(i != 1)
            printf(" ");
        printf("%d", ans[i]);
    }
    printf("\n");
}

void dfs(int count)
{
    int i;

    if(count == n) {
        if(prime[ans[count] + ans[1]])
            print_result();     // 输出结果
    } else {
        for(i=2; i<=n; i++)
            if(!visited[i] && prime[i + ans[count]]) {
                ans[count + 1] = i;
                visited[i] = 1;
                dfs(count + 1);
                visited[i] = 0;
            }
    }
}

int main(void)
{
    sieveofe(prime, N * 2 -1);

    int caseno=0;

    while(scanf("%d", &n) != EOF) {
        // 初始化标志
        memset(visited, 0, sizeof(visited));

        if(caseno != 0)
            printf("\n");
        printf("Case %d:\n",++caseno);

        // 深度优先搜索并且输出结果
        ans[1] = 1;
        visited[1] = 1;
        flag = 1;
        dfs(1);
    }

    return 0;
}


AC的C语言程序如下(UVA524):

/* UVA524 UVALive5270 Prime Ring Problem */

#include <stdio.h>
#include <memory.h>
#include <math.h>

#define MAXN 20

int ans[MAXN];
int visit[MAXN];
int n, count;

// 试除法判断一个数是否为素数
int isprime(int n)
{
    if((n & 1) == 0)  // 偶数:n % 2 == 0
        return 0;

    if(n == 3)
        return 1;

    int end = sqrt(n), i;
    for(i=3; i<=end; i+=2) {
        if(n % i == 0)
            break;
    }

    return i > end ? 1 : 0;
}

void print_result()
{
    int i;

    for(i=1; i<=n; i++) {
        if(i != 1)
            printf(" ");
        printf("%d", ans[i]);
    }
    printf("\n");
}

void dfs(int count)
{
    int i;

    for(i=2; i<=n; i++)
        if(!visit[i]) {
            if(isprime(ans[count] + i)) {
                count++;
                if(count == n) {
                    if(isprime(i + ans[1])) {
                        ans[count] = i;
                        print_result();     // 输出结果
                    }
                } else {
                    ans[count] = i;
                    visit[i] = 1;
                    dfs(count);
                    visit[i] = 0;
                }
                count--;
            }
        }
}

int main(void)
{
    int caseno=0;

    while(scanf("%d", &n) != EOF) {
        // 初始化标志
        memset(visit, 0, sizeof(visit));

        if(caseno != 0)
            printf("\n");

        printf("Case %d:\n",++caseno);

        // 深度优先搜索并且输出结果
        count = 1;
        ans[1] = 1;
        visit[1] = 1;
        dfs(count);
    }

    return 0;
}


posted on 2016-07-21 20:23  海岛Blog  阅读(144)  评论(0编辑  收藏  举报

导航