消化一个算法最重要的是理解他的思想,而不是急于搞定代码,写文章重要的是阐明道理,而不是简单的粘贴代码,这篇文章需要详细的分析!
符号三角形问题是经典的回溯问题,下图是一个符号三角形
+ + - +
+ - -
- +
-
这个三角形的组成规则是,只能由+和-组成,并且两个相同符号的下面是+,两个不同符号下面是-,设符号三角形第一行有n个符号,对于给定的n,计算有多少种不同的符号三角形,使得+和-的个数相等。例如,当n=4时,共有如下六种符号三角形满足条件
+ + - +
+ - -
- +
-
+ + - -
+ - +
- -
+
+ - + +
- - +
+ -
-
+ - + -
- - -
+ +
+
- + - +
- - -
+ +
+
- - + +
+ - +
- -
+
代码:
Code
1 class SymbolTriangles
2 {
3 // Print a solution
4 void Output(int n)
5 {
6 for (int i = 0; i < n; i++)
7 {
8 // Ouput space
9 for(int j = 0; j < i; j++)
10 Console.Write(" ");
11
12 // Output sign
13 for (int j = 0; j < n; j++)
14 {
15 if (i + j < n)
16 {
17 Console.Write(p[i, j] == 0 ? '+' : '-');
18 Console.Write(" ");
19 }
20 }
21
22 //next line
23 Console.WriteLine();
24 }
25 }
26
27 // Constraint
28 bool IsValid(int t, int n)
29 {
30 // totally we have n * (n + 1) / 2 signs, let half = n * (n + 1) / 2
31 // neither amout of '+' nor '-' should no more than half
32 return (count <= n * (n + 1) / 4) && ((t + 1) * (t + 2) / 2 - count <= n * (n + 1) / 4);
33 }
34
35 // Compute a solution, whether num of '+' equals to num of '-'
36 public void CountEqual(int t, int n)
37 {
38 if (t == n)
39 {
40 sum++;
41 Output(n);
42 }
43
44 else
45 {
46 for (int i = 0; i <= 1; i++)
47 {
48 p[0, t] = i;
49 count += i;
50
51 for (int j = 1; j <= t; j++)
52 {
53 p[j, t - j] = p[j - 1, t - j] ^ p[j - 1, t - j + 1];
54 count += p[j, t - j];
55 }
56
57 if (IsValid(t, n))
58 CountEqual(t + 1, n);
59
60 for (int j = 1; j <= t; j++)
61 {
62 count -= p[j, t - j];
63 }
64 count -= i;
65 }
66 }
67 }
68
69 // this function return the total number of solutions
70 // if we invoke this function, do not need to invoke Output function
71 public int Compute(int n)
72 {
73 CountEqual(0, n);
74 return sum;
75 }
76
77 // storage, make sure the dimension is bigger than the input argument n
78 private int[,] p = new int[20, 20];
79 private int count; // num of minus sign
80 private int sum; // number of solutions
81 }
82
83 class Program
84 {
85 static void Main(string[] args)
86 {
87 SymbolTriangles st = new SymbolTriangles();
88 st.CountEqual(0, 4);
89 //Console.WriteLine(st.Compute(12));
90 Console.ReadKey();
91 }
92 }