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

递归与分治策略 @半数集问题

2013年10月04日 ⁄ 综合 ⁄ 共 2844字 ⁄ 字号 评论关闭
 

一、算法实现题:半数集问题

1、问题描述:

给定一个自然数n,由n开始可以依次产生半数集set(n)中的数如下:

1n set(n);

2)在n的左边加上一个自然数,但该自然数不能超过最近添加的数的一半

3)按此规则进行处理,直到不能再添加自然数为止。

例如,set(6) = {6,16,26,126,36,136}。半数集set(6)中有6个元素。

注意,该半数集是多重集

2、编程任务:

对于给定的自然数n,计算半数集set(n)中的元素个数

3、数据输入:

输入数据由文件名为input.txt的文本文件提供。每个文件只有1行,给出整数n 0<n<1000)。

4、结果输出:

将计算结果输出到文件output.txt.输出文件只有一行,给出半数集set(n)中的元素个数。

      输入文件示例                       输出文件示例

      Input.txt                          output.txt

      6                                  6

二、解题思路

1、用递归实现

l  统计的结果用一个全局变量来记录,不能够在使用递归的函数中定义。

在主函数中定义一个记录结果的整形变量count,初始值为1。代码如下:

int count = 1; 

l  用循环从文件input.txt读取数据并将计算的结果存入output.txt文件中

while(fin_test_num>>Num)

  {

         count = 1;

         fun(Num/2,count);

         fout_test_num<<count<<"/n";

       }

l  关闭文件

fout_test_num.close();

fin_test_num.close();

l  自定义递归函数set计算,得到结果

在函数中利用一个for循环,每调用一次count 就增加n/2

2、算法改进(使用备忘录的方法):

l  使用递归算法效率较低,重复计算了先前已经计算过的值

               set(6/2)

                       

          set(1/2)   set(2/2)   set(3/2)

                            

                   set(1/2)   set(1/2)

如上图,重复计算了set(0)set(1)

为了解决上述问题,就应将已经计算的结果保存起来。

p[n]表示自然数m产生半数集的个数,则有如下关系:

     p[m] = 1+p[1]+p[2]+p[3]+ +p[n/2]   ( p[0] = 0 )

l  定义一个整形数组p ,空间大小为自然数n的一半。用count来记录p[n]的值,即最终结果。这样做的好处可以使循环的次数大大减小。

while(fin>>N)

  {

         count = 0;

         n = N/2;

         p = new int [n+1];

         for(i=0;i<=n;i++)

                p[i] = 0;

         for(i= 1;i<=n;i++)

         {

                int k = i/2;

                for(int j = 1;j <= k;j++)

                       p[i] += p[j];

                p[i] += 1;

                count += p[i];

         }

         count += 1;

         fout<<count<<"/n";

  }

 

三、算法描述 

1、用递归实现

#include <iostream>

#include <fstream>

using namespace std;

void set(int num,int &count)   //递归函数

{

       for (int i = 1; i <= num; i++)

       {

              count += 1;

              set(i/2,count);

       }

}

 

int main()

{

       int count = 1;

       int Num;

        //文件操作

       ifstream fin_test_num;

       ofstream fout_test_num;

       fout_test_num.open("output.txt");

       fin_test_num.open("input.txt");

       while(fin_test_num>>Num)   //从文件中读取数据

       {

              count = 1;    //重新设置count的值

              set(Num/2,count);  //调用递归函数进行计算

              fout_test_num<<count<<"/n";  //向文件中写入数据

       }

       fout_test_num.close();  //关闭文件

       fin_test_num.close();

       return 0;

}

 

2、用备忘录方法实现

#include <iostream>

#include <fstream>

using namespace std;

 

void main()

{

       int n,N,*p,count;

       int i = 0;

       ifstream fin;

       ofstream fout;

       fin.open("input.txt");

       fout.open("output.txt");

       while(fin>>N)

       {

              count = 0;

              n = N/2;

              p = new int [n+1];

              for(i=0;i<=n;i++)

                     p[i] = 0;

              for(i= 1;i<=n;i++)

              {

                     int k = i/2;

                     for(int j = 1;j <= k;j++)

                            p[i] += p[j];

                     p[i] += 1;

                     count += p[i];

              }

              count += 1;

              fout<<count<<"/n";

       }

       fin.close();

       fout.close();

}

抱歉!评论已关闭.