• 符号三角形——回溯法


    符号三角问题:

    下面都是“-”。 下图是由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);
    	    }
    	}
    

      

  • 相关阅读:
    Django的一点基本知识点
    python函数定义及作用域
    爬取妹子图片
    mysql常用命令大全
    python扫面端口
    python中重要的基础概念
    pexpect模块获取root密码
    mysql
    requests库
    C#中使用SQLite数据库简介(上)
  • 原文地址:https://www.cnblogs.com/www-x/p/8206592.html
Copyright © 2020-2023  润新知