符号三角形——回溯法
符号三角问题:
下面都是“-”。 下图是由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); } }
时间最会骗人,但也能让你明白,这个世界上没有什么是不能失去的,留下的尽力珍惜,得不到的都不重要