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

要求:

一个正整数n可以写为几个正整数的和,如:
4=4
4=3+1
4=2+2
4=2+1+1
4=1+1+1+1
输入一个正整数,找出符合这种要求的所有正整数序列(序列不重复)

算法思想:

 
以n=6为例,将数继序列暂时存于a[MAXCOL]中,且初始时值全为1。
对数组中从jcol列开始的newn个元素进行操作f(6,0,0)  ——函数GetCombinations(newn,newj,col)
col记录调用该函数时是在第col列。
 
初始化
count=6
j=0,newn=0
count=n
1. 如果count>1,令a[jcol]=count;
         若count>a[col],表明该尝试不满足条件,count=count-1,重复1;
         否则将该行第jcol+1列到jcol+count-1列的值改为0;
    否则,退出;
2. newn=n-count
3. 如果new>1,则对从该行开始从jcol+count开始的newn个元素进行类似操作,并返回该新的newn对应的序列个数;
    否则,count=count-1,返回1。

算法比较:

“acm题目及我的程序(3)——正整数n的加法组合”——使用二维数组存放加法序列
        #define MAXROW 12000
        #define MAXCOL 20
        a[MAXROW][MAXCOL]
        算法效率低,空间浪费严重
“acm题目及我的程序(3)——正整数n的加法组合(改进)”——使用二维数组存放加法序列
        a[MAXROW][MAXCOL]
        #define MAXROW 6000
        #define MAXCOL 30
        算法效率高,空间浪费不严重
 
“acm题目及我的程序(3)——正整数n的加法组合(改进2)”——使用动态二维数组存放加法序列
        vector<vector<int> > m_venline
        算法效率高,空间浪费很少
    
  本文算法——使用一维数组存放加法序列,且计算每个n的加法序列的个数
        a[MAXCOL]
        算法效率最高,空间根本不浪费

代码如下:

 
/************************************************************************
 * 一个正整数n可以写为几个正整数的和
 * 4=4
 * 4=3+1
 * 4=2+2
 * 4=2+1+1
 * 4=1+1+1+1
 * 要求:输入一个正整数,找出符合这种要求的所有正整数序列(序列不重复)
 ***********************************************************************
*/


#include 
< stdio.h >
#include 
< string .h >
#include 
< CONIO.H >
#include 
< vector >
using   namespace  std;

#define  MAXCOL 80
#define  FILENAMELENGTH 100

class  AdditionCombination
{
public:
    
int a[MAXCOL];
    
int m_number;    //条用GetCombinations函数时count的值    

public:
    AdditionCombination(
int number)
    
{
        m_number
=number;
        
for(int j=0;j<MAXCOL;j++)
            a[j]
=1;
    }


    
~AdditionCombination(){}

    
void Initialize()
    
{
        
for(int j=0;j<m_number;j++)
            a[j]
=1;
    }


    
void Initialize(int jcol)
    
{
        
for(int j=jcol;j<m_number;j++)
            a[j]
=1;
    }


    
int GetCombinations(int n,int jcol,int col);
    
void display(int n);
}
;

// 在数组中从irow行,jcol列开始对n阶子矩阵进行
// col记录调用该函数前jcol的值
int  AdditionCombination::GetCombinations( int  n, int  jcol, int  col)
{
    
int nTotalCount=0;
    
int j=0,newn=0;
    
int count=n;
    
    
while(count>1)
    
{
        
if(jcol==0)
            Initialize();
        
else
            Initialize(jcol);
        a[jcol]
=count;
        
        
//算法优化,删除不满足的序列
        if(a[jcol]>a[col])
        
{
            count
--;
            
continue;
        }


        
for(j=jcol+1;j<jcol+count;j++)
            a[j]
=0;

        newn
=n-count;
        
if(newn>1)
        
{
            
int newj=jcol+count;
            
int newcount=GetCombinations(newn,newj,jcol);
            nTotalCount
+=newcount;
        }

        
        count
--;
        
//display(m_number);
        nTotalCount++;
    }


    
if(jcol==0)
    
{
        Initialize();
        
//display(m_number);
        nTotalCount++;
    }

    
else
        Initialize(jcol);

    
return nTotalCount;
}


void  AdditionCombination::display( int  n)
{
    printf(
"   %d=%d",n,a[0]);
    
for(int j=1;j<n;j++)
    
{
        
if(a[j])
            printf(
"+%d",a[j]);
    }

}


// 将结果写入文件
void  WriteToFile(vector < vector < int >   >  info)
{
    
char filename[FILENAMELENGTH];

    
int size=info.size();
    
//构造文件名
    sprintf(filename,"%d-%d result.txt",info[0][0],info[size-1][0]);
    FILE 
*fp=fopen(filename,"w");
    
if(fp==NULL)
    
{
        printf(
"can not wirte file!");
        exit(
0);
    }


    
//写入个数
    for(int i=0;i<size;i++)
        fprintf(fp,
"n=%d    count=%d ",info[i][0],info[i][1]);

    fclose(fp);
}


// 显示菜单
void  show_menu()
{
    printf(
"--------------------------------------------- ");
    printf(
"input command to test the program ");
    printf(
"   i or I : input n to test ");
    printf(
"   t or T : get count from n1 to n2 ");
    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(n);
            
int count=obj.GetCombinations(n,0,0);
            printf(
"   count = %d ",count);
        }

        
else if(stricmp(sinput,"t")==0)
        
{
            
int n1,n2;
            printf(
"  please input the begin number:");
            scanf(
"%d",&n1);
            printf(
"  please input the  end  number:");
            scanf(
"%d",&n2);

            printf(
"  press any key to start ... ");
            getch();

            vector
<vector<int> > info;
            vector
<int> line;

            AdditionCombination obj(n1);
            
for(int i=n1;i<=n2;i++)
            
{
                obj.Initialize();
                obj.m_number
=i;
                
int count=obj.GetCombinations(i,0,0);
                printf(
"  n=%d    count=%d ",i,count);
                line.clear();
                line.push_back(i);
                line.push_back(count);
                info.push_back(line);
            }

            printf(
" ");

            
//写入文件
            printf("$ write the numbers to file(Y,N)? >");
            scanf(
"%s",sinput);
            
if(stricmp(sinput,"y")==0)        //写入文件
            {
                WriteToFile(info);
                printf(
"  write successfully! ");
            }

            printf(
" ");
        }


        
//输入命令
        printf("$ input command >");
        scanf(
"%s",sinput);
    }

}

运行结果如下:

输入从n1=30到n2=40的测试结果:

acm题目及我的程序(3)——正整数n的加法组合 (完美版)_第1张图片

n1=1,n2=80的结果如下(文件1-80 result.txt):

n=1    count=1
n=2    count=2
n=3    count=3
n=4    count=5
n=5    count=7
n=6    count=11
n=7    count=15
n=8    count=22
n=9    count=30
n=10    count=42
n=11    count=56
n=12    count=77
n=13    count=101
n=14    count=135
n=15    count=176
n=16    count=231
n=17    count=297
n=18    count=385
n=19    count=490
n=20    count=627
n=21    count=792
n=22    count=1002
n=23    count=1255
n=24    count=1575
n=25    count=1958
n=26    count=2436
n=27    count=3010
n=28    count=3718
n=29    count=4565
n=30    count=5604
n=31    count=6842
n=32    count=8349
n=33    count=10143
n=34    count=12310
n=35    count=14883
n=36    count=17977
n=37    count=21637
n=38    count=26015
n=39    count=31185
n=40    count=37338
n=41    count=44583
n=42    count=53174
n=43    count=63261
n=44    count=75175
n=45    count=89134
n=46    count=105558
n=47    count=124754
n=48    count=147273
n=49    count=173525
n=50    count=204226
n=51    count=239943
n=52    count=281589
n=53    count=329931
n=54    count=386155
n=55    count=451276
n=56    count=526823
n=57    count=614154
n=58    count=715220
n=59    count=831820
n=60    count=966467
n=61    count=1121505
n=62    count=1300156
n=63    count=1505499
n=64    count=1741630
n=65    count=2012558
n=66    count=2323520
n=67    count=2679689
n=68    count=3087735
n=69    count=3554345
n=70    count=4087968
n=71    count=4697205
n=72    count=5392783
n=73    count=6185689
n=74    count=7089500
n=75    count=8118264
n=76    count=9289091
n=77    count=10619863
n=78    count=12132164
n=79    count=13848650
n=80    count=15796476

  

你可能感兴趣的:(acm题目及我的程序(3)——正整数n的加法组合 (完美版))