rqnoj286 小明学算术 题解

      今天太纠结了,上午的模拟赛又杯具了,依然110,后悔自己没有下狠心把那个integer改成longint…整个一个下午就调了一道弱小的DFS,别的同学一节课就过了…程序一直202,过了一会就201,直到自己把自己的代码改的和RQ上的题解几乎完全一样的时候也没有解决…最后还是请同学帮忙,被他BS自己没有弄懂自己打的代码什么意思…最近的效率太低了,要想办法提高!

      下面切入正题。

 

【题目描述】(rqnoj286)

小明最近接到了一项算数的作业。黑板上初始时只有一个数1。每次取在黑板上的任意两个数(可以相同)相加,得到另一个数,要求这个数比黑板上已有的任意一个数都大,并把所得的符合要求的和数也写在黑板上。这称为一次操作。当黑板上首次出现指定的整数n(2<=n<=1000)时,停止操作。

小明的加法学得很不好,算一次加法需要很长时间。他希望学编程的你找到一种方案,用最少的操作次数得出指定的数n。





【输入格式】

只有一行。包含一个整数n(2<=n<=1000),表示指定的整数。



【输出格式】

两行。第一行一个整数,表示最少操作次数。第二行若干个空格隔开的整数,表示操作结束时黑板上的所有数,按从小到大的顺序输出。若有多组符合要求的解,输出次大的数最大的一组;若还多解,输出第三大的数最大的一组;以此类推。



【样例输入】

样例输入1

2

样例输入2

200

 

【样例输出】

样例输出1

1

1 2

样例输出2

9

1 2 4 8 16 32 64 128 192 200

 

      因为搜索的范围很明显,所以DFS很好写。但是要注意题目上说的输出要求,所以要在达到当前最优解时对存储解的数组进行判断是否更新。最重要的,整个搜索过程状态极多,n的值大了就很容易栈溢出。所以在进行递归调用之前要加一个判断条件,如果压栈的数目接近栈的容量时就停止搜索,直接输出当前解即可。

 

      参考代码:

 

  
    
1 program calculate;
2 type
3 list = array [ 0 .. 1000 ] of longint;
4 var
5 n:integer;
6 tot,lim:longint;
7 f,t,tt:list; // f数组存储的是当前的队列
8 function min(n:integer):list;
9 var
10 i:integer;
11 begin
12 for i: = 1 to n do
13 if t[i] < f[i] then exit(f)
14 else exit(t);
15 end ;
16 procedure print;
17 var
18 i:integer;
19 begin
20 writeln(tot);
21 for i: = 1 to tot + 1 do
22 write(t[i], ' ' );
23 end ;
24 procedure dfs(x:longint);
25 var
26 i,j:longint;
27 begin
28 if x > n then exit; // 队列中的数的个数超出n就剪掉(用处不大)
29 if x > tot then exit; // 最优化剪枝
30 for i: = x downto 1 do // 枚举各种组合
31 begin
32 for j: = i downto 1 do
33 begin
34 if f[x] > f[i] + f[j] then exit; // 和要大于任何一个数
35 if f[i] + f[j] = n then // 更新最优解
36 begin
37 if x < tot then
38 begin
39 t: = f;
40 tot: = x;
41 t[tot + 1 ]: = n;
42 end
43 else if x = tot then // 题目的要求
44 begin
45 t: = min(tot);
46 t[tot + 1 ]: = n;
47 end ;
48
49 exit;
50 end ;
51 if n > f[i] + f[j] then
52 begin
53 if lim >= 10000000 then // 限制入栈次数
54 begin
55 print;
56 halt;
57 end ;
58 f[x + 1 ]: = f[i] + f[j]; // 入队
59 inc(lim);
60 dfs(x + 1 );
61 end ;
62 end ;
63 end ;
64 end ;
65 begin
66 readln(n);
67 tot: = 10000000 ;
68 f[ 1 ]: = 1 ;
69 dfs( 1 );
70 print;
71 end .
 

 

 

(saltless原创,转载请注明出处)

你可能感兴趣的:(题解)