球盒问题之二:n分解成m正数和解题代码

来源:互联网 发布:提字器软件 编辑:程序博客网 时间:2024/06/12 01:34

球盒问题之二:n分解成m正数和解题代码

在上一篇博文 球盒问题之一:方案概览 中给出了S(n,m)的代码实现方案。
而对于前2种情况的解决方案并未给出代码与问题解决的思路。在这里,就将第一种与第二种情况下的解决问题的思路与代码分享。

思路:

第一种情况,n球同,m盒同,不空。记解为D(n,m)。
第二种情况,n球同,m盒同,可空,记解为H(n,m)。

那第一种情况与第二种情况有什么关系呢。先看第一种情况,因为所有盒子都不空,那所有盒子至少放一个球。那要是先将每个盒子都先放一个球呢,还剩下n-m个球要放到m个盒子中。而此时m个盒子中已经有一个球了,所以问题就退化成了将n-m个球放到m个盒子中,可以有空盒子这种情况下的解。

即 D(n,m)=H(n-m,m)。

而从上一篇博客我们已经知道了H(n,m)是D(n,1)加上D(n,2)。。。一直加到D(n,m)。

聪明如你,一定会想到,如果用数学来解决这个问题,那这就可以组成一个二元方程组。

而当用计算机解决这类方程式相关的问题时,就可以用动态规划相关的思路了。说白了就是递归调用直到将问题递归转化成最简单情况下的子集,然后求解。

解题代码如下:

class SplitNumToHeap{public:    SplitNumToHeap():runTimes_(0){};    virtual ~SplitNumToHeap(){};    //盒不可空    int splitNotEmpty(int ball,int box){        if(ball == box || 1 == box)            return 1;        else if(ball<box)            return 0;        runTimes_++;        return splitCanEmpty(ball-box,box);    };    //盒可空    int splitCanEmpty(int ball,int box){        if(1==box || 1==ball)            return 1;        return sumFunctionNotEmpty(ball,box);    };    //球数不变,盒数从1到最大值,计算盒不空所有放法之和。    int sumFunctionNotEmpty(int ball,int boxMax){        int result =0;        for(int i=1;i<=boxMax;i++)        {            result+=splitNotEmpty(ball,i);            runTimes_++;        }        return result;    };    //运行次数统计    int getRunTimes(){return runTimes_;};    void clear(){runTimes_=0;};private:    int runTimes_;};

用盒不可空(n分解为m个数之和)做了几次测试,数据如下:

ball 100 put in box 99 can 1 runTimes 1ball 100 put in box 50 can 204226 runTimes 543737ball 100 put in box 25 can 7037286 runTimes 18973294ball 100 put in box 10 can 2977866 runTimes 8313067ball 100 put in box 2 can 50 runTimes 147ball 10 put in box 4 can 9 runTimes 21ball 10 put in box 5 can 7 runTimes 15ball 8 put in box 5 can 3 runTimes 7ball 8 put in box 3 can 5 runTimes 12ball 8 put in box 4 can 5 runTimes 9ball 8 put in box 6 can 2 runTimes 7ball 9 put in box 6 can 3 runTimes 8ball 11 put in box 6 can 7 runTimes 16ball 5 put in box 6 can 0 runTimes 0ball 5 put in box 3 can 2 runTimes 4ball 15 put in box 3 can 19 runTimes 48ball 15 put in box 8 can 15 runTimes 37

用几个参数核对了下,能对上。比如8分3个数和是和,10分2个数和是5等。

测试与打印代码基于Qt5.3,如下:

void MainWindow::on_BtnBallBox_clicked(){    SplitNumToHeap split;    int ball=ui->lineEditBall->text().toInt();    int box=ui->lineEditBox->text().toInt();    int solutions=split.splitNotEmpty(ball,box);    ui->lineEditSolutions->setText(QString::number(solutions));    ui->lineEditRunTimes->setText(QString::number(split.getRunTimes()));    std::cout<<"ball "<<ball<<" put in box "<<box<<" can "<<solutions<<" runTimes "<<split.getRunTimes()<<std::endl;    split.clear();}
0 0
原创粉丝点击