符号三角问题:
下面都是“-”。 下图是由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);
}
}