UVA524 UVALive5270 HDU1016 ZOJ1457 Prime Ring Problem【DFS】

708 篇文章 19 订阅
281 篇文章 4 订阅

 

Prime Ring Problem

 

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 60401    Accepted Submission(s): 26099

 

 

Problem Description

A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime.

Note: the number of first circle should always be 1.

 

 

Input

n (0 < n < 20).

 

 

Output

The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order.

You are to write a program that completes above process.

Print a blank line after each case.

 

 

Sample Input

 

68

 

Sample Output

 

Case 1:1 4 3 2 5 61 6 5 2 3 4Case 2:1 2 3 8 5 6 7 41 2 5 8 3 4 7 61 4 7 6 5 8 3 21 6 7 4 3 8 5 2

 

 

Source

Asia 1996, Shanghai (Mainland China)

 

 

 

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;
}

 

 

 

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值