标签:
华电北风吹
天津大学认知计算与应用重点实验室
最后修改日期: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;
end
for 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
end
end
主函数:
clear;clc;
global t; % 需要划分的数
global p; % 记录符合条件划分次数
p=0;
t=input(‘输如需要划分数:‘);
a=[];
func(a);
disp(‘最终划分种类数p=‘)
p
法二:后向
从最后一位向第一位依次向前计算。方法思路跟第一种类似。但是是从后往前循环计算,如果后面k位可以划分就对后面k位进行划分,直到划分出全部为1的和结束。然后对第一位降1继续对后面划分。
MATLAB代码:
% mainfunction
clear;clc;
n=input(‘请输入n的值:‘);
if n==1
disp(‘1=1‘);
return;
end
if n==2
disp(‘2=1+1‘)
return;
end
a=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
end
end
补充 当只需要知道划分个数,不需要知道方案细则的可以采用下面方案,对于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
end
end
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/zhangzhengyi03539/article/details/47102345