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原创,转载请注明出处)

posted on 2010-08-06 18:17  saltless  阅读(389)  评论(1编辑  收藏  举报

导航