acm题目及我的程序(3)——正整数n的加法组合 (改进)

本文介绍了一种求解正整数n的所有加法组合的算法,通过优化避免重复序列,实现高效查找所有可能的正整数序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对“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
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个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值