对“acm题目及我的程序(3)——正整数n的加法组合”的改进
要求:
一个正整数n可以写为几个正整数的和,如:
4=4
4=3+1
4=2+2
4=2+1+1
4=1+1+1+1
输入一个正整数,找出符合这种要求的所有正整数序列(序列不重复)
算法思想:
在求解的过程中,直接判断,如果序列中的某个数据大于前面的数据,则直接进行下一次计算,以提高效率。
以n=6为例,将数继序列存于a[MAXROW][6]中,且将数组a的所有值初始化为1
对数组中从irow行,jcol列开始的newn阶子矩阵进行操作f(6,0,0,0) ——函数GetCombinations(newn,newi,newj,col)
col记录调用该函数时是在第col列。
初始化
count=6
j=0,newn=0;
i=0
i=0
count=n
1. 如果count>6,令a[i][jcol]=count;
若count>a[i][col],表明该尝试不满足条件,count=count-1,重复1;
否则将该行第jcol+1列到jcol+count-1列的值改为0;
否则,退出;
2. newn=n-count
3. 如果new>1,则对从该行开始从jcol+count开始的newn阶子矩阵进行类似操作,并返回增加的行数,并将该行的前jcol个元素复制到新增加的每一行;
否则,count=count-1,处理下一行
代码如下:

/**//************************************************************************
* 一个正整数n可以写为几个正整数的和
* 4=4
* 4=3+1
* 4=2+2
* 4=2+1+1
* 4=1+1+1+1
* 要求:输入一个正整数,找出符合这种要求的所有正整数序列(序列不重复)
************************************************************************/
#include <stdio.h>
#include <string.h>
#define MAXROW 12000
#define MAXCOL 20
class AdditionCombination
...{
public:
int a[MAXROW][MAXCOL];
public:
AdditionCombination()...{}
~AdditionCombination()...{}
void Initialize(int n);
int GetCombinations(int n,int irow,int jcol,int col);
void display(int n,int count);
};
void AdditionCombination::Initialize(int n)
...{
for(int i=0;i<MAXROW;i++)
for(int j=0;j<MAXCOL;j++)
a[i][j]=1;
}
//在数组中从irow行,jcol列开始对n阶子矩阵进行
//col记录调用该函数前jcol的值
int AdditionCombination::GetCombinations(int n,int irow,int jcol,int col)
...{
if(n==2)
...{
a[irow][jcol]=2;
a[irow][jcol+1]=0;
return 2;
}
int j=0,newn=0;
int i=irow; //from line irow
int count=n; //count is the number of 1 to be added
while(count>1)
...{
a[i][jcol]=count;
//算法优化,删除不满足的序列
int comi=0;
if(a[i][col]==1)
comi=irow;
else
comi=i;
if(a[i][jcol]>a[comi][col]) //unvalid line
...{
count--;
continue;
}
for(j=jcol+1;j<jcol+count;j++)
a[i][j]=0;
newn=n-count;
if(newn>1)
...{
int newi=i;
int newj=jcol+count;
int newcount=GetCombinations(newn,newi,newj,jcol);
//copy the front count elements of the ith line for newn-1 times
for(int k=1;k<newcount;k++)
...{
for(int t=jcol;t<newj;t++)
a[newi+k][t]=a[newi][t];
}
i+=newcount;
count--;
}
else
...{
i++;
count--;
}
}
return i-irow+1;
}
void AdditionCombination::display(int n,int count)
...{
for(int i=0;i<count;i++)
...{
printf(" %d=%d",n,a[i][0]);
for(int j=1;j<n;j++)
...{
if(a[i][j])
printf("+%d",a[i][j]);
}
}
printf(" count=%d ",count);
}
//显示菜单
void show_menu()
...{
printf("--------------------------------------------- ");
printf("input command to test the program ");
printf(" i or I : input n to test ");
printf(" q or Q : quit ");
printf("--------------------------------------------- ");
printf("$ input command >");
}
void main()
...{
char sinput[10];
int n;
show_menu();
scanf("%s",sinput);
while(stricmp(sinput,"q")!=0)
...{
if(stricmp(sinput,"i")==0)
...{
printf(" please input an integer:");
scanf("%d",&n);
AdditionCombination obj;
obj.Initialize(n);
int count=obj.GetCombinations(n,0,0,0);
obj.display(n,count);
}
//输入命令
printf("$ input command >");
scanf("%s",sinput);
}
}运行结果如下:
n=10
直接找到n=10的所有满足条件的序列为42个
本文介绍了一种求解正整数n的所有加法组合的算法,通过优化避免重复序列,实现高效查找所有可能的正整数序列。

被折叠的 条评论
为什么被折叠?



