回溯法解符号三角形

消化一个算法最重要的是理解他的思想,而不是急于搞定代码,写文章重要的是阐明道理,而不是简单的粘贴代码,这篇文章需要详细的分析!

符号三角形问题是经典的回溯问题,下图是一个符号三角形

+ + - +
 + - -
  - +
   -

这个三角形的组成规则是,只能由+和-组成,并且两个相同符号的下面是+,两个不同符号下面是-,设符号三角形第一行有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[2020];
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(04);
89             //Console.WriteLine(st.Compute(12));
90             Console.ReadKey();
91         }
92     }

你可能感兴趣的:(回溯法解符号三角形)