寻找表达式(dfs)

题目来源:微策略2013年校园招聘笔试题
题目描述:

现在有一个序列123......N,其中N介于3和15之间,要求在序列之间加入+、-或者空格,使得该序列组成的数学表达式的运算结果为0。

输入:

输入可能包含多个测试样例。
对于每个测试案例,输入整数N(3<=N<=15),代表这个序列的长度。

输出:

对应每个测试案例,输出所有使得表达式结果为0的组合,当有多个组合时,按字典序进行排序输出。

样例输入:
3
6
样例输出:
1+2-3
1 2+3-4-5-6
提示:

 1_2+3-4-5-6相当于12+3-4-5-6(‘_’代表空格)

思路:

  对于3<=n<=15,总共有3^n种情况,当n=15时,总共有14348907种情况,所以对于给定的n,我们都可以在1秒内穷举完。对于穷举,当然用dfs是最方便的,我写的代码基本是对所有的情况都遍历一遍,当然如果觉得效率还不行,可以加些适当的减枝。代码如下:

 1 #include <stdio.h>
 2 
 3 int n;
 4 int op[20];
 5 
 6 void print_ans()
 7 {
 8     int i;
 9 
10     for (i = 1; i < n; i ++)
11     {
12         printf("%d", i);
13         if (op[i] == 0)
14             printf(" ");
15         else if (op[i] == 1)
16             printf("+");
17         else
18             printf("-");
19     }
20     printf("%d\n", i);
21 }
22 int is_ok()
23 {
24     int i, ans, temp;
25 
26     if (op[1] == 0)
27         ans = 0;
28     else
29         ans = 1;
30     i = 1;
31     while (i < n)
32     {
33         if (op[i] == 0)
34         {
35             temp = i;
36             while (i < n && op[i] == 0)
37             {
38                 i ++;
39                 if (i >= 10)
40                     temp *= 10;
41                 temp = temp * 10 + i;
42             }
43             ans += temp;
44         }
45         else if  (op[i] == 1)
46         {
47             temp = ++i;
48             while (i < n && op[i] == 0)
49             {
50                 i ++;
51                 if (i >= 10)
52                     temp *= 10;
53                 temp = temp * 10 + i;
54             }
55             ans += temp;
56         }
57         else
58         {
59             temp = ++i;
60             while (i < n && op[i] == 0)
61             {
62                 i ++;
63                 if (i >= 10)
64                     temp *= 10;
65                 temp = temp * 10 + i;
66             }
67             ans -= temp;
68         }
69     }
70     return ans;
71 }
72 void dfs(int index)
73 {
74     if (index == n)
75     {
76         if (!is_ok())
77             print_ans();
78         return;
79     }
80     //空格
81     op[index] = 0;
82     dfs(index + 1);
83     //
84     op[index] = 1;
85     dfs(index + 1);
86     //
87     op[index] = 2;
88     dfs(index + 1);
89 }
90 int main(void)
91 {
92     while (scanf("%d", &n) != EOF)
93         dfs(1);
94     return 0;
95 }
View Code

  关键的代码是dfs函数,分别对空格,加,减进行穷举,op[index]存放了第index位置存放的是哪种情况(0表示空格,1表示加,2表示减),如果index为n,则说明得到了一种可能,函数is_ok就是用于判断当前的情况是否能使得表达式最终的结果为0,如果为0,则输出并返回,否则直接返回。

  is_ok函数是用于判断放在op数组中的表达式是否满足条件,计算表达式比较麻烦的是为空格的情况,由于空格可以首先出现,在“+”后面出现,在“-”后面出现,is_ok中的代码则依次处理这三种情况。还有就是如果空格后面是个2位数,空格前面组成的数要向左移动两位,如果是1位数,只用移动1位。

 

posted @ 2013-07-25 09:01  在于思考  阅读(1252)  评论(2编辑  收藏  举报