整数划分方案

来源:互联网 发布:不可谓知类 编辑:程序博客网 时间:2024/05/30 07:12

华电北风吹
最后修改日期:2015/7/28

根据每一种划分里面最大的数进行划分。

为此,先规定我们的划分结果数字重视按照从大到小的顺序输出的比如9可以划分为1、2、2、4,我们划分时均把每一类划分最大的元素放在第一位,次大的第二位……,例如4,2,2,1。

法一:前向
为了避免重复,我们可以先对于每一种划分的第一个数进行分类有1、2、3、4……9共9类,然后对每一种类进行再次划分(比如对于第一个数字为5,就需要对5以后进行划分,不过后面分配的数不能超过第一个数。所以第一个数字为5时,第二个数字就可以取1、2、3、4,然后继续对第三个数字划分,直到最后加和为9),这时每得到的一种划分方法就是9的所有的无重复的一种划分方法。
MATLAB代码:
递归函数:

function f=func(a)global t;       % 需要划分的数global p;       % 记录符合条件划分次数temp=sum(a);k=length(a);if k>0                             % 第一次进入递归函数进入else   result=min([t-temp a(k)]);     % 确定本步接下来分配次数else   result=t-temp;endfor i=result:-1:1   b=[a i];   if sum(b)==t                   % 符合输出条件的b输出       p=p+1;        disp(['第',num2str(p),'种划分法']);       b   else                           % 不符合输出条件的b递归       if sum(b)           func(b);       end   endend

主函数:

clear;clc;global t;       % 需要划分的数global p;       % 记录符合条件划分次数p=0;t=input('输如需要划分数:');a=[];func(a);disp('最终划分种类数p=')p

法二:后向
从最后一位向第一位依次向前计算。方法思路跟第一种类似。但是是从后往前循环计算,如果后面k位可以划分就对后面k位进行划分,直到划分出全部为1的和结束。然后对第一位降1继续对后面划分。
MATLAB代码:

% mainfunctionclear;clc;n=input('请输入n的值:');if n==1   disp('1=1');   return;endif n==2   disp('2=1+1')   return;enda=zeros(1,n);a(1)=n;     % 数组a为长度为n的一维数组top=2;      % 指向当前分配长度下一位k=0;        % 记录分配次数while true   k=k+1;   % 输出当前满足条件的分配方案   disp(['第',num2str(k),'种划分法']);   result=[];   for i=1:n       if a(i)>0           result=[result a(i)];       end   end   result   % 把数组a后面所有需要分配的数加起来,包括所有的1和一个非1   s=0;   while true       top=top-1;       s=s+a(top);       if top>1&&a(top)==1           continue       else           break;  % a(top)大于1       end   end             % top更新为指向最后一位大于1的数   if a(1)==1       break;   end;   % 对当前a重新分配   d=a(top)-1;   if d==1       % s分到top后面每个数全为1分配       while s>0           a(top)=1;           s=s-1;           top=top+1;       end   else       % s分到top后面按d分配,最后一个为余数       while s>d           a(top)=d;           top=top+1;           s=s-d;       end       if s~=0           a(top)=s;           top=top+1;       end   endend

补充 当只需要知道划分个数,不需要知道方案细则的可以采用下面方案,对于divide函数由于包含很多重复计算,可以设置一个字典用来保存已经计算过的(n,m)用空间换时间

function f=divide(n,m)if m==1||n==1   f=1;else   if n<m       f=divide(n,n);   else       if n==m           f=1+divide(n,m-1);       else           if n>m                f=divide(n-m,m)+divide(n,m-1);           end       end   endend
1 0
原创粉丝点击