ACM素数环问题(c++和python3)

1. 题目

        素数环是一个由数字 1, 2, ..., n 构成的圆环,其中任意两个相邻数字之和均为素数,圆环中的数字不能重复。

- Input: 输入包含多组测试数据,每组数据占一行,为素数环的大小 n (0 < n < 18)。
- Output: 对于每组数据,按字典序大小,输出所有素数环的排列方案,排列方案的第一个数字必须是 1,每组数据后要输出一个空行。

2.解题思路

        非常明显,这是一道回溯的题目。从1开始,每个空位有20种可能,只要填进去的数合法:与前面的数不相同;与左边相邻的数的和是一个素数。第20个数还要判断和第1个数的和是否素数。

        搜索与回溯是计算机解题中常用的算法,很多问题无法根据某种确定的计算法则来求解,可以利用搜索与回溯的技术求解。回溯是搜索算法中的一种控制策略。它的基本思想是:为了求得问题的解,先选择某一种可能情况向前探索,在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索,如此反复进行,直至得到解或证明无解。

3.编程

3.1 使用C++语言

程序

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

int n,a[20],v[21];

int prime(int m)   //判断m是否是素数
{
    int i;
    for(i=2;i<=sqrt(m);i++)//判素数只要循环到根号m
        if(m%i==0)
            break;
    if(i<=sqrt(m))
        return 0;
    return 1;
}

void dfs(int r)
{
    int i,j;
    if(r==n)
    {
        if(prime(a[r-1]+1))
        {
            for(j=0;j<n;j++)
                printf(j==n-1?"%d\n":"%d ",a[j]);
        }
        return;
    }
    for(i=2;i<=n;i++)
    {
        if(!v[i]&&prime(a[r-1]+i))//如果“素数环”中没出现过i,并且i和相邻元素的值相同
        {
            v[i]=1;
            a[r]=i;//更新并标记
            dfs(r+1); //搜索下一个数
            v[i]=0;//回溯
        }
    }
}

int main()
{
    int c=0;
    while(scanf("%d",&n)!=EOF)
    {
        printf("Case %d:\n",++c);
        if(n%2==0)
        {
            memset(v,0,sizeof(v));
            a[0]=v[1]=1;
            dfs(1);
        }
        puts("");
    }
    return 0;
}

测试

C:\Users\zhangyy\CLionProjects\Ctest\cmake-build-debug\Ctest.exe
7 8 9 10
Case 1:

Case 2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2

Case 3:

Case 4:
1 2 3 4 7 6 5 8 9 10
1 2 3 4 7 10 9 8 5 6
1 2 3 4 9 8 5 6 7 10
1 2 3 8 5 6 7 4 9 10
1 2 3 8 5 6 7 10 9 4
1 2 3 10 7 4 9 8 5 6
1 2 3 10 7 6 5 8 9 4
......
1 10 9 8 5 2 3 4 7 6
1 10 9 8 5 6 7 4 3 2

3.2 使用python语言

程序

p = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]
t = 0


def pround(r, a=[1]):
    global p
    if r == []:
        if a[0] + a[-1] in p:
            c = 0
            for i in a:
                if c != 0:
                    print(" ", end="")
                print(i, end='')
                c += 1

            print()
    else:
        for i in range(len(r)):
            if r[i] + a[-1] in p:
                pround(r[:i] + r[i + 1:], a + [r[i]])


try:
    while True:
        t += 1
        r = list(range(2, eval(input()) + 1))
        print("Case %d:" % t)
        pround(r)
        print()
except:
    pass

测试

C:\Users\zhangyy\PycharmProjects\ACM_Test\venv\Scripts\python.exe C:\Users\zhangyy\PycharmProjects\ACM_Test\main.py 
8
Case 1:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2

9
Case 2:

4. 最后

        找到一个递归回溯算法代码框架,分享下,希望能有所帮助。

递归回溯法算法框架[一]
int Search(int k)
{
   for (i=1;i<=算符种数;i++)
    if (满足条件)
     {
      保存结果
      if (到目的地) 输出解;
       else Search(k+1);
      恢复:保存结果之前的状态{回溯一步}
     }
}
递归回溯法算法框架[二]
int Search(int k)
{
   if  (到目的地) 输出解;
   else
    for (i=1;i<=算符种数;i++)
     if  (满足条件) 
       {
        保存结果;
            Search(k+1);
        恢复:保存结果之前的状态{回溯一步}
       }
}

猜你喜欢

转载自blog.csdn.net/qq_33163046/article/details/128259638