Chinaunix首页 | 论坛 | 博客
  • 博客访问: 229346
  • 博文数量: 39
  • 博客积分: 1130
  • 博客等级: 少尉
  • 技术积分: 453
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-26 15:54
文章分类

全部博文(39)

文章存档

2012年(1)

2011年(31)

2010年(7)

分类: C/C++

2011-06-28 21:03:14

11.完成qiongju()函数的框架
    除了对数字的各种组合进行穷举,qiongju()函数还需要完成计算各数字N次方之和并验算是否满足花朵数条件这两个功能。用伪代码表示就是
  1. /*2_穷举.c*/
  2. #include "2_穷举.h"
  3. #include "0_问题.h" //用到了QIUJIE、WEISHU
  4. extern void qiongju( void )
  5. {
  6.   static int sz = JINZHI , gs_sx ; /*关于哪个数字 ,该数字个数的上限*/
  7.   //static 数据类型 各数字N次方和 ;
  8.   switch ( sz ) {
  9.      case JINZHI : //递归准备工作
  10.          gs_sx = WEISHU ;
  11.          sz -- ;
  12.          //各数字N次方和 = 0 ;
  13.          qiongju();
  14.          sz = JINZHI ;
  15.          return ;
  16.      default : //递归过程
  17.          {
  18.             int i ;
  19.             for( i = 0 ; i <= gs_sx ; i++ ){
  20.                //求和
  21.                //各数字N次方和 += i * sz^N ;
  22.                sz -- ;
  23.                gs_sx -= i ;
  24.                qiongju ();
  25.                //各数字N次方和 -= i * sz^N ;
  26.                gs_sx += i ;
  27.                sz ++ ;
  28.             }
  29.             return ;
  30.          }
  31.      case 0 : //递归终止
  32.          //<=>验算<=>记录结果
  33.          //验证是否满足花朵数条件:
  34.          //判断 各数字N次方和 中的数字是否与构成组合的数字集一致
  35.          return ;
  36.   }
  37. }
  
   //static 数据类型 各数字N次方和 ;
     由于“各数字N次方和”可能很大,通常的数据类型无法描述,所以必须建立新的数据类型来描述这种数据。这种类型用于表示并存储较大的整数,所以命名为DASHU_t(大数)。由于各次递归调用传递数据的需要,所以必须定义成static存储类别。
     之后为 各数字N次方和 取名为 he_szNf。
     //static 数据类型 各数字N次方和 ;
==》//static DASHU_t he_szNf ; //各数字N次方和 ;
12.进一步的分析   
     一种新的数据类型如何定义,不仅决定于这种类型存储什么样的数据,而且要受到这种数据将要进行的运算的约束。为此需要考察分析在qiongju()函数中he_szNf 都需要做哪些运算。
     //各数字N次方和 = 0 ;
     这里需要对  各数字N次方和 赋值,这里需要写一个函数完成赋值功能。
     //各数字N次方和 += i * sz^N ;
    这里要求计算 各数字N次方和 与 i * sz^N的和。i * sz^N 与 he_szNf一样可能是一个很大的非负整数,因此可考虑用同样的类型描述。
    由于在递归过程中i * sz^N这个值可能反复用到,每次都计算这个值势必徒增无谓的运行时间。所以应该在递归之前计算并存储起来,这就是所谓空间换时间。
    由于对每个数字需要 sz^N,2*sz^N……WEISHU*sz^N(0*sz^N不需要)这些值,且一共有JINZHI个数字,因而可以把这些数据组织成数组
    static DASHU_t N次幂倍数表[JINZHI-1][WEISHU];
    数组的第一维尺寸为JINZHI-1是因为数字0计算时不用考虑。 定义为static 的原因同样是因为这些数据在各层递归中都要用到。
13.N次幂倍数表的定义和初始化
   在qiongju()给出数组定义 N次幂倍数表(Ncimi_bsb) 的定义之后需要考虑这个数组的初始化问题。这个数组显然应该在case JINZHI :部分初始化。伪代码如下
  1. extern void qiongju( void )
  2. {
  3.   static int sz = JINZHI , gs_sx ; /*关于哪个数字 ,该数字个数的上限*/
  4.   //static DASHU_t he_szNf ;//static 数据类型 he_szNf ; //各数字N次方和 ;
  5.   //static DASHU_t Ncimi_bsb[JINZHI-1][WEISHU]//N次幂倍数表[JINZHI-1][WEISHU]
  6.   switch ( sz ) {
  7.      case JINZHI : //递归准备工作
  8.          gs_sx = WEISHU ;
  9.          sz -- ;
  10.          // 各数字N次方和 = 0 ;
  11.          // 初始化 ( Ncimi_bsb ) ;
  12.          qiongju();
  13.          sz = JINZHI ;
  14.          return ;
  15.      default : //递归过程
  16.          {
  17.             int i ;
  18.             for( i = 0 ; i <= gs_sx ; i++ ){
  19.                //求和
  20.                //各数字N次方和 += i * sz^N ;
  21.                sz -- ;
  22.                gs_sx -= i ;
  23.                qiongju ();
  24.                //各数字N次方和 -= i * sz^N ;
  25.                gs_sx += i ;
  26.                sz ++ ;
  27.             }
  28.             return ;
  29.          }
  30.      case 0 : //递归终止
  31.          //<=>验算<=>记录结果
  32.          //验证是否满足花朵数条件:
  33.          //判断 各数字N次方和 中的数字是否与构成组合的数字集一致
  34.          return ;
  35.   }
  36. }
 
    不难想到,调用 初始化 (  N次幂倍数表 )过程中,各个数字的N次幂的倍数(最大为WEISHU)可能会超过 WEISHU 位,但由于花朵数的条件是 WEISHU 位,所以若某数字的N次幂的倍数超过 WEISHU 位只需能够表示而不必精确表示其值。这对DASHU_t类型的要求是能够表示溢出(超过WEISHU 位),但必须能精确表示WEISHU 位JINZHI进制非整数。
    此外如果这张表的各项是通过乘法完成的,那么DASHU_t类型应该保证乘的过程中不至于溢出,这样DASHU_t中存储的数据需要满足 (DASHU_t)(X)*WEISHU    如果这张表的各项是通过加法(用加法实现乘法)求得的,则这种类型的数据只需(DASHU_t)(X)
14.求和
    对一种新的数据类型做求和运算,在C语言中通常只能通过函数完成。qiongju()函数中的 //求和 部分可以写为
   //求和( & he_szNf , i * sz^N );
   亦即
   //求和( & he_szNf , & Ncimi_bsb[sz][i] );
   前一个参数使用指针的缘故是需要通过函数调用改变 he_szNf ,后一个是为了减少传递参数的时间消耗。
   求和对DASHU_t类型的要求不高,只要存储的内容不超过 UMANX 的一半就可以了。
15.减法
     //各数字N次方和 -= i * sz^N ;实际上可以通过增加变量的办法省略。亦即用一个auto局部变量记住最初的 各数字N次方和 ,待递归调用返回时再用这个auto局部变量恢复 各数字N次方和 原来的值。
    由于这里需要用到赋值运算,因此这种类型最好能直接赋值。很多数据类型都可以直接赋值,比如struct,所以可初步确定DASHU_t为某种struct类型。
  1. /*2_穷举.c*/
  2. #include "2_穷举.h"
  3. #include "0_问题.h" //用到了QIUJIE、WEISHU
  4. extern void qiongju( void )
  5. {
  6.   static int sz = JINZHI , gs_sx ; /*关于哪个数字 ,该数字个数的上限*/
  7.   //static DASHU_t he_szNf ;//static 数据类型 he_szNf ; //各数字N次方和 ;
  8.   //static DASHU_t N次幂倍数表[JINZHI-1][WEISHU]
  9.   switch ( sz ) {
  10.      case JINZHI : //递归准备工作
  11.          gs_sx = WEISHU ;
  12.          sz -- ;
  13.          // 各数字N次方和 = 0 ;
  14.          // N次幂倍数表 初始化
  15.          qiongju();
  16.          sz = JINZHI ;
  17.          return ;
  18.      default : //递归过程
  19.          {
  20.             int i ;
  21.             DASHU_t he_szNf_ = he_szNf ;//记录进入时的 he_szNf
  22.             for( i = 0 ; i <= gs_sx ; i++ ){
  23.                //求和
  24.                //各数字N次方和 += i * sz^N ;
  25.                //求和( & he_szNf , & Ncimi_bsb[sz][i] );
  26.                sz -- ;
  27.                gs_sx -= i ;
  28.                qiongju ();
  29.                //各数字N次方和 -= i * sz^N ;
  30.                he_szNf = he_szNf_ ; //改回原来的he_szNf
  31.                gs_sx += i ;
  32.                sz ++ ;
  33.             }
  34.             return ;
  35.          }
  36.      case 0 : //递归终止
  37.          //<=>验算<=>记录结果
  38.          //验证是否满足花朵数条件:
  39.          //判断 各数字N次方和 中的数字是否与构成组合的数字集一致
  40.          return ;
  41.   }
  42. }
16.验算部分
    验算的基本原理是考察最终所得到的he_szNf的各个组成数字是否与最初提供数字组合中出现的数字一致。为此必须记录提供组合时的各个数字出现的次数。显然static数组就可以实现记录功能。     //static unsigned 各数字的次数[JINZHI];
    其中,各数字的次数[i]记录数字i在组合中的个数。伪代码如下:
  1. /*2_穷举.c*/
  2. #include "2_穷举.h"
  3. #include "0_问题.h" //用到了QIUJIE、WEISHU
  4. extern void qiongju( void )
  5. {
  6.   static int sz = JINZHI , gs_sx ; /*关于哪个数字 ,该数字个数的上限*/
  7.   //static DASHU_t he_szNf ;//static 数据类型 he_szNf ; //各数字N次方和 ;
  8.   //static DASHU_t N次幂倍数表[JINZHI-1][WEISHU]
  9.   //static unsigned 各数字的次数[JINZHI];
  10.   switch ( sz ) {
  11.      case JINZHI : //递归准备工作
  12.          gs_sx = WEISHU ;
  13.          sz -- ;
  14.          // 各数字N次方和 = 0 ;
  15.          // N次幂倍数表 初始化
  16.          qiongju();
  17.          sz = JINZHI ;
  18.          return ;
  19.      default : //递归过程
  20.          {
  21.             int i ;
  22.             DASHU_t he_szNf_ = he_szNf ;//记录进入时的 he_szNf
  23.             for( i = 0 ; i <= gs_sx ; i++ ){
  24.                //记录数字sz的个数
  25.                // 各数字的次数[sx] = i ;
  26.                //求和
  27.                //各数字N次方和 += i * sz^N ;
  28.                //求和( & he_szNf , & Ncimi_bsb[sz][i] );
  29.                sz -- ;
  30.                gs_sx -= i ;
  31.                qiongju ();
  32.                //各数字N次方和 -= i * sz^N ;
  33.                he_szNf = he_szNf_ ; //改回原来的he_szNf
  34.                gs_sx += i ;
  35.                sz ++ ;
  36.             }
  37.             return ;
  38.          }
  39.      case 0 : //递归终止
  40.          //<=>验算<=>记录结果
  41.          //验证是否满足花朵数条件:
  42.          //判断 各数字N次方和 中的数字是否与构成组合的数字集一致
  43. // 各数字的次数[0] = gs_sx ;
  44. // if( 数字集一致(he_szNf,各数字的次数)){
  45. // //记录
  46. // }
  47.          return ;
  48.   }
  49. }
  
   函数 数字集一致() 需要求出 he_szNf 中各个数字出现的次数,这对DASHU_t这种类型的要求是希望算法的实现比较简单。
     至此,可以考虑如何设计DASHU_t这种数据类型了。

17.对DASHU_t类型的要求汇总
   根据前面对计算过程的分析,可归纳出程序对DASHU_t类型的要求:
   ①最好能直接赋值
   ②能够精确表示WEISHU位JINZHI进制数
   ③能够表示WEISHU位以上的JINZHI进制数
   ④在进行 *WEISHU 、*(JINZHI-1)、加法运算时不产生溢出
   ⑤能方便地求出对应的JINZHI进制数的各位数字
阅读(2318) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~