1. 程式人生 > >素數環(簡單的回溯運用)

素數環(簡單的回溯運用)

題目描述

輸入正整數n,把整數1,2,3,…n組成一個環,使得相鄰兩個整數之和均為素數。輸出時從整數1開始逆時針排列。同一個環應恰好只輸出一次。n<=16

#include"stdio.h"
int n;
static int vis[17];運用的是靜態性的變數,初值為0;此VIs陣列表對應的a陣列中的是否使用
static int a[17];//儲存每一位將排位的數

int isfrime(int x,int y)//判斷,x,y的和是不是素數。
{
    int s=x+y;
    int i;
    for(i=2;i<s;i++)
    {
        if(s%i==0)
            break;
    }
    if(s==i)
        return 1;
    else
        return 0;
}
int dfs(int k)//這是回溯的最關鍵部分,利用遞迴完成回溯。k為a的下標,當k==n+1了, 則表示a陣列賦值已經到了最後一個下標值了。
{
    int i,j;
    if(k==n+1)//遞迴結束條件
    {   if(!(isfrime(a[n],a[1])==1))//因為素數環,所以最後一個值和第一個值相加也要為素數 若不為,則返回 return 0;
             return 0;
        for(i=1;i<n;i++)//輸出陣列a中的每一個數 
            printf("%d ",a[i]);
        printf("%d\n",a[n]);
        return 0;
    }
    else//繼續給陣列a賦值利用遞迴
    {
        for(i=2;i<=n;i++)
        {
            if(vis[i]==0&&isfrime(a[k-1],i))//vis[i]為0,則表示i未被使用過。
            {
                vis[i]=1;//表i已使用過
                a[k]=i;並將i的值賦給a陣列中。
                dfs(k+1);繼續遞迴給k+1的下標位置賦值
                vis[i]=0;//dfs結束 ,並釋放點i
            }
        }
    }
}
int main()
{
    a[1]=1;
    while(~scanf("%d",&n))
 {


        dfs(2);//因為第一個元素必須為1, 所以下標位置從2開始
 }
}