野心家

导航

符号三角形——回溯法

符号三角问题:

下面都是“-”。 下图是由14个“+”和14个“-”组成的符号三角形。2个同号下面都是“+”,2个异号下面都是“-”。 

   +   +    -    +    -    +    +

     +    -    -    -    -     +

        -    +   +   +   -

          -    +   +   -

            -   +   -

              -   -

                +

在一般情况下,符号三角形的第一行有n个符号。符号三角形问题要求对于给定的n,计算有多少个不同的符号三角形,使其所含的“+”和“-”的个数相同。

package com.lanxi.demo1;
import java.util.Scanner;
public class Triangle {
	    static int n;//第一行的符号个数
	    static int half;//n*(n+1)/2
	    static int count;//当前+号的个数
	    static int[][] p;//符号三角形矩阵
	    static long sum;//已找到的符号三角形个数
	    static int signAll;
	    public static long compute(int nn){
	        n=nn;//第一行符号个数
	        count=0;//初始化当前“+”
	        sum=0;//符合条件的符号三角形
	        signAll = n*(n+1)/2;//第一行全部符号数量
	        if(signAll%2==1) return 0;//如果第一行某一种符号大于一半,则退出
	        half=signAll/2;//一半符号数量
	        p=new int[n+1][n+1];//创建数组
	        //初始化数组,将二维数组初始化为0
	        for(int i=0;i<=n;i++){
	            for(int j=0;j<=n;j++){
	                p[i][j]=0;

	            }
	        }       
	        backtrack(1);//开始算法
	        return sum;//返回结果
	    }
	    public static void backtrack(int t){
	        //若+号统计未超过半数或-号超过半数,返回
	        if(count>half||(t*(t-1)/2-count)>half)
	            return ;
	        if(t>n)
	            sum++;
	        else{
	            for(int i=0;i<2;i++){
	                //第一行第t个符号
	               p[1][t]=i;
	                count+=i;
	                //当第一行符号>=2时,可以运算出下面行的某些符号,j可代表行号
	                for(int j=2;j<=t;j++){
	                    //从上往下构造符号数组
	                    //核心代码
	                    p[j][t-j+1]=p[j-1][t-j+1]^p[j-1][t-j+2];
	                    //^:按位异或。比如二进制
	                    //1001 ^ 1100 = 0101  0^0=0,1^1=0 ,1^0 = 1,0^1=1。
	                    count+=p[j][t-j+1];//当前“+”的数量
	                }
	                if((count<=half)&&(t*(t+1)/2-count<=half)){
	                    //+号未超过半数,并且另一种符号也未超过半数则继续
	                    backtrack(t+1);
	                }
	                //回溯,判断另一种符号情况
	                for(int j=2;j<=t;j++){
	                    //恢复对count的操作
	                    count-=p[j][t-j+1];
	                }
	                count-=i;
	            }
	        }
	        
	    }
	    public static void main(String[] args) {
	        System.out.println("请输入一个整数:");
	        Scanner input=new Scanner(System.in);
	        int num=input.nextInt();//第一行符号个数	       
	        long result=compute(num);
	        System.out.println(result);
	    }
	}

  

posted on 2018-01-05 20:07  野心家  阅读(527)  评论(0编辑  收藏  举报