一、Problem
符号三角形的第1行有n个由“+”和”-“组成的符号 ,以后每行符号比上行少1个,2个同号下面是”+“,2个异号下面是”-“ 。计算有多少个不同的符号三角形,使其所含”+“ 和”-“ 的个数相同。
n=7 时的 1 个符号三角形如下:
+ + - + - + +
+ - - - - +
- + + + -
- + + -
- + -
- -
+
输入
每行1个正整数n<=24,n=0退出.
输出
n和符号三角形的个数.
样例输入
15
16
19
20
0
1
2
3
4
5
样例输出
15 1896
16 5160
19 32757
20 59984
二、Solution
方法一:暴搜(2.8 s)
- 由于组合数非常多,通过构造合法三角形有点不现实。
- 不妨看看题目,由于存在同号得正,异号得负的定理,下一行的符号也就可以通过上一行的符号推算出来。
- 所以,我们只需要枚举第一行的排列。
- 又由于
0^0=0;1^1=0;1^0=1;0^1=1
,所以我们可以让 1 表示正,0 表示负。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static int[][] g;
static int res;
static int n;
static void op() {
int tot1 = 0, tot2 = 0;
for (int c = 0; c < n; c++) {
if (g[0][c] == 1) tot1++;
else tot2++;
}
for (int i = 1; i < n; i++)
for (int j = 0; j < n-i; j++) {
g[i][j] = g[i-1][j] ^ g[i-1][j+1];
if (g[i][j] == 1) tot1++;
else tot2++;
}
if (tot1 == tot2)
res++;
}
static void dfs(int x) {
if (x == n) {
op();
return;
}
g[0][x] = 1;
dfs(x+1);
g[0][x] = 0;
dfs(x+1);
}
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
while(true) {
n = sc.nextInt();
if (n == 0)
break;
g = new int[n][n];
dfs(0);
System.out.printf("%d %d\n", n, res);
res = 0;
}
}
}
复杂度分析
- 时间复杂度: ,
- 空间复杂度: ,
剪枝优化:
- 因为题目要求我们求出的具有相同符号数的三角形,以下情况可提前结束搜索:
- 如果 ‘+’ 和 ‘-’ 的总数和是一个奇数。
- 当前“+”或“-”已经大于总数的一半,结束本次搜索。
- 当前数目加上剩余的全部数目仍小于总数的一半。