vijos p1117(数的划分)(100)

我想说,题目的意思有误啊!!!!

他说任意两份不能相同,我就以为分成的每个部分都不能相同...但他的意思是这是个组合,不是排列(即不考虑顺序问题....)

被坑了.....

算法: 递归+记忆化搜索

顺便说一下 个人比较喜欢用 haha来作为函数的名称.....

ans:=haha(n,k,min).  意思是从 把n 分成 k份的方案数,至于后面的1。意思是分出来的每份的值小于min(初始值为1),这个东西在后面有用。

因为我们要得出的是一个组合,不是排列,所以我们可以设每次的方案分出的数的序列都是一个不降的序列,如此就有:

当k>=2 时,我们有haha(n,k,min):=haha(n,k,min)+haha(n-i,k-1,i);如果其中(min<=i<=n).

当k=1 时, haha(n,k,min):=1;(分成一份当然只有一种方案)。

优化:递归的缺点就是有很多重复的计算,所以我们可以另开一个三维数组来记录每一次函数的值,如果再需计算这个函数,我们先检查这个函数是否已经在数组里记录过了,如果已经记录,直接调用数组,否则再计算函数。

代码:

 1 program p1117;
 2 var
 3         i,j,k,l,m,n:longint;
 4         ha:array[0..200,0..6,0..200]of longint;
 5 function haha(n,k,min:longint):longint;
 6 var
 7         i,j:longint;
 8 begin
 9         haha:=0;
10         if k=1 then
11                 begin
12                 if n<min then haha:=0
13                 else begin haha:=1; ha[n,k,min]:=1; end;
14                 end
15         else
16         for i:=min to n do
17                 begin
18                 if ha[n-i,k-1,i]<>0then
19                         haha:=haha+ha[n-i,k-1,i]
20                 else haha:=haha+haha(n-i,k-1,i);
21                 end;
22         ha[n,k,min]:=haha;
23 end;
24 begin
25         fillchar(ha,sizeof(ha),0);
26         read(n,k);
27         m:=haha(n,k,1);
28         write(m);
29 end.

还要加油啊!

posted @ 2012-12-08 20:07  改名字干什么  阅读(324)  评论(0编辑  收藏  举报