现在的位置: 首页 > 综合 > 正文

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

2013年10月23日 ⁄ 综合 ⁄ 共 4695字 ⁄ 字号 评论关闭

要求:

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

算法思想:

在“acm题目及我的程序(3)——正整数n的加法组合”中,我们使用二维数组存放加法序列,实现规定MAXROW和MAXCOL,这样的数组在程序运行时分配的内存在栈区,其大小受限制,程序定义的MAXROW和MAXCOl如下:
#define MAXROW 12000
#define MAXCOL 20
所以运行时,n最大不能超过20,且n=20时,其求解出的所有序列为10946个,但满足条件的序列仅有627个,故时间和空间浪费都很严重。
而在“acm题目及我的程序(3)——正整数n的加法组合(改进)”中,虽然空间的严重浪费解决的很好,但还是有部分空间浪费,程序定义的MAXROW和MAXCOl如下:
 
#define MAXROW 6000
#define MAXCOL 30
所以在n很小时,例如n=12时,求出满足条件的序列有77个,空间浪费也很严重,而n最大为30时,求出的序列为5604个,也有浪费。
故在此文中,将存储空间改为动态二维数组,采用vector实现,且在求解的过程中,直接判断,如果序列中的某个数据大于前面的数据,则直接进行下一次计算,即节省空间,又提高了效率。但因vector为数据容器,对其操作都是采用其标准函数,而不像数组直接对内存读写,效率会稍微有些降低。
 
以n=6为例,将数继序列存于vector<vector<int> > m_vecline中,且初始时m_vecline为空,只是在需要的时候才向该数组增加一行。
对数组中从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,令m_vecline[i][jcol]=count;
         若count>m_vecline[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>
#include 
<vector>
using namespace std;

#define FILENAMELENGTH 100    //文件名长度

class AdditionCombination
{
public:
    vector
<vector<int> > m_vecline;
    
int m_number;

public:
    AdditionCombination(
int n){m_number=n;m_vecline.clear();}
    
~AdditionCombination(){}

    
void AddANewLine(int row);
    
int GetCombinations(int n,int irow,int jcol,int col);
    
void display(int n,int count);
    
void WriteToFile(int n,int count);
}
;

//add a new line including n valus 1
void AdditionCombination::AddANewLine(int row)
{
    
if(row>=m_vecline.size())
    
{
        vector
<int> line;
        
for(int i=0;i<m_number;i++)
            line.push_back(
1);
        m_vecline.push_back(line);
    }

}


//在数组中从irow行,jcol列开始对n阶子矩阵进行
//col记录调用该函数前jcol的值
int AdditionCombination::GetCombinations(int n,int irow,int jcol,int col)
{
    
if(n==2)
    
{
        AddANewLine(irow);
        m_vecline[irow][jcol]
=2;
        m_vecline[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)
    
{
        AddANewLine(i);
        m_vecline[i][jcol]
=count;
        
        
//算法优化,删除不满足的序列
        int comi=0;
        
if(m_vecline[i][col]==1)
            comi
=irow;
        
else
            comi
=i;
        
if(m_vecline[i][jcol]>m_vecline[comi][col])    //unvalid line
        {
            count
--;
            
continue;
        }


        
for(j=jcol+1;j<jcol+count;j++)
            m_vecline[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
            AddANewLine(i+newcount);
            
for(int k=1;k<newcount;k++)
            
{
                
for(int t=jcol;t<newj;t++)
                    m_vecline[newi
+k][t]=m_vecline[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,m_vecline[i][0]);
        
for(int j=1;j<n;j++)
        
{
            
if(m_vecline[i][j])
                printf(
"+%d",m_vecline[i][j]);
        }

    }

    printf(
"   count=%d   vector size=%d ",count,m_vecline.size());
}


//将结果写入文件
void AdditionCombination::WriteToFile(int n,int count)
{
    
char filename[FILENAMELENGTH];

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


    
//写入个数
    fprintf(fp,"total number = %d ",count);
    
for(int i=0;i<count;i++)
    
{
        fprintf(fp,
"   %d=%d",n,m_vecline[i][0]);
        
for(int j=1;j<n;j++)
        
{
            
if(m_vecline[i][j])
                fprintf(fp,
"+%d",m_vecline[i][j]);
        }

    }


    fclose(fp);
}


//显示菜单
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

抱歉!评论已关闭.