素数环问题

来源:互联网 发布:旅游约伴用什么软件 编辑:程序博客网 时间:2024/04/28 18:32
问题描述:
      
 
将从1到n这n个整数围成一个圆环,若其中任意2个相邻的数字相加,结果均为素数,那么这个环就成为素数环。

20以内的素数环:
1  2  3  4 
1  4  3  2  5  6
1  2  3  8  5  6  7  4
1  2  3  4  7  6  5  8  9  10
1  2  3  4  7  6  5  12  11  8  9  10 
1  2  3  4  7  6  13  10  9  14  5  8  11  12
1  2  3  4  7  6  5  12  11  8  9  14  15  16  13  10
1  2  3  4  7  6  5  8  9  10  13  16  15  14  17  12  11  18
1  2  3  4  7  6  5  8  9  10  13  16  15  14  17  20  11  12  19  18

算法设计:
       
利用回溯法穷举所有可能性,找到一个后,结束程序。具体来讲,就是在第一个位置先设置为1,然后第二个位置试试2行不行,再在第三个位置试试3行不行,再在第四个位置试试4行不行,再在第五个位置试试5,发现不行,然后试试6,发现还不行,再试试7,终于可以了,继续往下试验……

代码编写:
import java.util.Arrays;
import java.util.Random;

public class MyTest {
    
public static void main(String[] args) {
        
        
int length = 22;      //素数环的长度
        int[] b = new int[length];    //一个数组,用来标识第i个数字是否被使用过。
        Arrays.fill(b, 0);      //将数组初始化为0,标识所有数字尚未被使用
        int[] ring = new int[length];      //用于存放最终素数环的数组
        ring[0= 1;                                //素数环的第一个数字必然为1(因为是个环,我们从1那一点开始考虑就行了)
        if(primeNumRing(b, ring, 1))
            printArray(ring);
        
else
            System.out.println(
"不存在素数环");

    }

    
        
//负责打印数组,最后输出素数环的时候用得着
    public static void printArray(int a[]) {
        
for(int x:a) {
            System.out.print(x
+"  ");
        }

        System.out.println();
    }

    
        
//用递归的方法判断素数环
        
//数组b用来标识某个数字是否被使用过了,数组ring用来存储素数环
       
//整数n表示当前正在考察素数环中的第几个数字
    private static boolean primeNumRing(int[] b, int[] ring, int n) {
               
//当最后一个数字考察完毕后,测试一下他加上第一个数字(也就是1)是不是素数
               
//如果是素数,那么就说明找到了素数环,如果不是,则没有找到
        if(n == b.length)
            
return isPrimeNum(ring[n-1]+1);
               
//start是循环的开始点,因为奇数的旁边必然是偶数,偶数的旁边必然是奇数
              
//因此若前一个数是偶数,那么当前考察的必然全是奇数,反之亦然
              
//因此,循环的跨度为2
        int start = 2-n%2;
        
for(int i=start; i<b.length; i+=2{
                        
//如果当前考察的数字没有被使用过,并且和前一个数字相加的和为素数的话
            if(b[i]==0 && isPrimeNum((i+1)+ring[n-1])) {
                b[i] 
= 1;            //将其标识设置为"已使用"
                ring[n] = i+1;   //将其放入素数环中
                                
//如果他后面的所有数字都符合要求,则找到素数环,反之将标识清零后,考察下一个数字
                if(primeNumRing(b, ring, n+1))
                    
return true;
                
else
                    b[i] 
= 0;
            }

        }

        
return false;
    }

    
        
//判断一个数是否为素数
       
//这里没有使用通用的判别方法,一般来讲,素数环都不会超过30个数字
       
//因此需要判断的最大的数字不会超过60。
       
//本函数的测试因子最大为11,也就是说凡是小于168(13的平方)的素数都能够被判断,够用了
    private static boolean isPrimeNum(int x) {
        
int[] primeNums = {235711};
        
int i;
        
for(i=0; i<primeNums.length; i++{
            
if(x>primeNums[i] && x%primeNums[i] == 0)
                
break;
        }

        
return (i==primeNums.length);
    }

}