【搜索】C034_oenj_符号三角形(搜索 + 递推)

一、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;
		}
    }
}

复杂度分析

  • 时间复杂度: O ( 2 n ) O(2^n)
  • 空间复杂度: O ( n ) O(n)

剪枝优化:

  • 因为题目要求我们求出的具有相同符号数的三角形,以下情况可提前结束搜索:
    • 如果 ‘+’ 和 ‘-’ 的总数和是一个奇数。
    • 当前“+”或“-”已经大于总数的一半,结束本次搜索。
    • 当前数目加上剩余的全部数目仍小于总数的一半。
发布了714 篇原创文章 · 获赞 199 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_43539599/article/details/105642902