码迷,mamicode.com
首页 > 其他好文 > 详细

回溯法第5题—自然数的拆分问题

时间:2014-08-13 18:24:16      阅读:607      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   for   ar   art   问题   div   

[问题描述]输入自然数n,然后将其拆分成由若干数相加的形式,参与加法运算的数可以重复。

输入:待拆分的自然数n。

输出:若干数的加法式子。

[样例输入]

7

[样例输出]

7=1+6
7=1+1+5
7=1+1+1+4
7=1+1+1+1+3
7=1+1+1+1+1+2
7=1+1+1+1+1+1+1
7=1+1+1+2+2
7=1+1+2+3
7=1+2+4
7=1+2+2+2
7=1+3+3
7=2+5
7=2+2+3
7=3+4

[问题分析]

很明显是数的组合题目,需满足两个条件:

(1)每一组数之和必须等于n;

(2)每一组数的个数是不确定的;

我们可以使等式中的后一个数的大小一定大于或等于前一个数,也就是不下降串,这样可以避免剪枝,提高效率。

//下面是我写的程序,代码很短,标程有一些细节没有考虑,因此标程暂不给出

var a,b:array [1..100]  of  byte;
    n:integer;
procedure try(m,start,k:integer);{探求第k个可取的数}
{m表示待拆分的数值,start表示可拆分数的起始值}
var i,j:integer;
begin
 for i:=start to (m>>1) do{m>>1 == m div 2}
  begin
   a[k]:=m-i;b[k]:=i;{a数组表示待拆分的数,b数组表示参与拆分的数}
   write(n,=);
   for j:=1 to k do write(b[j],+);
   writeln(a[k]);
   try(a[k],i,k+1);
  end;
end;
begin
  readln(n);
  try(n,1,1);
end.

如果感到这道题有些难理解,我们可以一步一步的来执行:

(下面以n=7为例)

首先,我们try(n,1,1);

a[1]=6,b[1]=1;

然后我们就可以输出7=1+6;

然后try(6,1,2)对6进行拆分,a[2]=6-1=5,b[2]=1,于是又可以输出7=1+1+5;

接着try(5,1,3),a[3]=5-1=4,b[3]=1,于是有7=1+1+1+4;

try(4,1,4),得到a[4]=4-1=3,b[4]=1,输出7=1+1+1+1+3;

try(3,1,5),a[5]=3-1=2,b[5]=1,print(7=1+1+1+1+1+2);

try(2,1,6),a[6]=2-1=1,b[6]=1,print(7=1+1+1+1+1+1+1);

try(1,1,7),不满足循环条件,回溯

回到上一步,循环已经结束,回溯

回到上一步,循环已经结束,回溯

回到上一步,a[4]=4-2=2,b[2]=2,print(7=1+1+1+2+2)

try(2,2,5),不满足循环条件,回溯

回到上一步,a[3]=5-2=3,b[3]=2,print(7=1+1+2+3)

try(3,2,4),不满足循环条件,回溯

回到上一步,a[2]=6-2=4,b[2]=2,print(7=1+2+4)

try(4,2,3),满足循环条件,循环一次

a[3]=4-2=2,b[3]=2,print(7=1+2+2+2)

……………………………………

后面执行的就不写了,经过这一番执行,想必大家对这个问题都有了新的认识。

那么我这费大力气写出执行过程也就很有价值了。

回溯法第5题—自然数的拆分问题,布布扣,bubuko.com

回溯法第5题—自然数的拆分问题

标签:style   blog   color   for   ar   art   问题   div   

原文地址:http://www.cnblogs.com/cuichen/p/3910464.html

(1)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!