回溯解决素数环问题

问题描述

素数环是一个计算机程序问题,指的是将从1到n这n个整数围成一个圆环,若其中任意2个相邻的数字相加,结果均为素数

思路分析

我们可以根据问题建成一个根节点为1深度为n的n叉数。通过对解空间的进行回溯剪枝(条件就是相邻两元素和为素数以及是否重复使用)就可以得到所有解。

java实现

public class PrimeRing {
	protected int k, x[], count;//k叉树,x[]存放一个解,count可行方案数
	public PrimeRing(int k, int n) //初始化参数,k为k叉数,在这个问题中k=n,n是树高及一个解的深度。
    {
        this.k = k;
        this.x = new int[n];                     
        x[0] = 1;     //元素初值为1
        this.count = 0;
    }
	public void printAll()//打印
	{
		this.count = 0;
		this.backtrack(1);
		System.out.println("" + count + "个解");
	}
	public static boolean isPrime(int n) { //判断是否为素数
		for(int i = 2; i < Math.sqrt(n)+1; i++) {
			if(n%i == 0)
				return false;
		}
		return true;
	}
	protected void backtrack(int i) //实现方法
		{
	    	//回溯
	        if (i < this.x.length) {
	        	for (int j = 1; j <= this.k; j++)  //遍历k个子树
	            {
	        		this.x[i] = j;              //结点取值,范围1~k
	                if (restrict(i)) {        //约束剪枝
	                	this.backtrack(i+1);         //遍历下一棵子树,获得解x[i+1]值,递归调用
	                }    
	            } 
	        }
	        else { //到达叶子结点,获得一个解
	        		if (isPrime(x[x.length-1] + x[0])){
	                	count ++;
	                	this.print(); // 输出当前方案
	           	 	}
	       		}    
	    }
	    protected boolean restrict(int i)     //约束条件,包括约束剪枝和限界剪枝 i当前位置 
	    {
	    	if (isPrime(x[i-1] + x[i])) {
	    		for(int j = 0; j < i; j++) { //查重
	    			if(x[i] == x[j]) {
	    				return false;
	    			}
	    		}
	    		return true;
	    	}
	    	return false;
	    }
	    protected void print()                       //输出一个解x[],值为0/1,形式为“(,)”
	    {
	        if (this.x.length > 0)
	        {
	            System.out.print(this.x[0]);
	            for (int i=1; i < this.x.length; i++)
	                System.out.print("," + this.x[i]);
	            System.out.println();
	        }
	    }
	    public static void main(String args[])
	    {
	    	new PrimeRing(8,8).printAll();
	    }
}

结果示例
回溯解决素数环问题_第1张图片

你可能感兴趣的:(#,回溯)