zoukankan      html  css  js  c++  java
  • 代码意识流——花朵数问题(三)

    本文前一部分的链接
    http://www.cnblogs.com/KBTiller/archive/2011/05/31/2064262.html

    7.更直接了当的穷举方案

      既然第二种方案在本质上无非是给出各位数字的各种组合,那么也许不如索性更直接一些。第3种方案虽然略有些抽象但却更加直接。
      方案3.
          for( 数字(JINZHI-1)的个数=0 ; 数字(JINZHI-1)的个数<=总位数 ; 数字(JINZHI-1)的个数++)
             for( 数字(JINZHI-2)的个数=0 ;数字(JINZHI-2)的个数<=总位数-数字(JINZHI-1)的个数 ; 数字(JINZHI-2)的个数++ )
                …… 
               for( 数字1的个数=0 ; 数字1的个数<=总位数-前面各数字个数之和 ; 数字1的个数++)
               {
                    //数字0的个数= 总位数-前面各数字个数之和
                    //<=>验算<=>记录结果
               }

      这种方案循环嵌套的深度比第二种方案要浅,对于数量巨大的计算更有优势。       
    8.测试方案可行性
      对3进制5位数情况测试方案是否可行。
    修改

    /*2_穷举.c*/
    
    #include "2_穷举.h"
    
    extern void qiongju( void )
    {
      int n2;
      
      for(n2=0;n2<=WEISHU;n2++){
        int n1;
    
        printf("%d个%d ",n2,JINZHI-1);
    
        for(n1=0;n1<=WEISHU-n2;n1++)
        {  
           int n0;
    
           printf("%d个%d ",n1,JINZHI-2);  
    
           {
            n0 = WEISHU - n2 - n1 ;  
            printf("%d个%d",n0,0);
            putchar('\n');
             //<=>验算<=>记录结果
           }
        }
    
      }
      
    }
    

    修改

    /*0_问题.h*/ 
    
    #ifndef WENTI_H  
    #define WENTI_H   
     
        #define CESHI        //进行测试    
        //#define QIUJIE     //求解21位问题                                
           
       #ifdef CESHI             //测试  
    
          #define JINZHI 3//10      //十进制   
          #define WEISHU 5//3       //3位花朵数     
          #define N      WEISHU  //幂次==位数   
    
        #endif //CESHI  
           
        #ifdef QIUJIE            //求解              
    
          #define JINZHI 10      //十进制   
          #define WEISHU 21      //位数      
          #define N      WEISHU  //幂次==位数   
    
        #endif //QIUJIE  
           
    #endif // WENTI_H 
    

    修改

    /*2_穷举.h*/
    
    #ifndef QIONGJU_H
    #define QIONGJU_H 
    
       #include "0_问题.h"  //函数qiongju( )用到了JINZHI、WEISHU         
    /**************************类型定义**************************/ 
    
    
    
    /**************************函数原型**************************/ 
       
       extern void qiongju( void );
    
    #endif // QIONGJU_H
    

      运行结果符合期待,表明方案可行。         
    9.把嵌套改成递归          
       循环嵌套只能描述固定层数的嵌套结构,所以前面的方案只能写出某特定进制的情况(3进制2层循环……10进制9层循环)。如果希望代码对不同进制的问题都成立,需要把循环的嵌套改成函数的递归,即用函数描述每一层循环及最内层的循环体部分的运算。
      即使是只考虑十进制的情况,这样的修改也是必要的。因为循环嵌套的结构复杂、繁琐,不利于修改(后面应该还有许多内容需要添加)和维护。况且,写9层循环多少有些让人不寒而栗,至少对我来说是这样,不痛下决心是没勇气写9层循环嵌套的。
      每一层循环(包括最内层的循环体)都需要两个参数确定:枚举的是哪个数字,这个数字的个数最多有几个(上限)。以第一层循环为例

        for(n2=0;n2<=WEISHU;n2++){
          printf("%d个%d ",n2,JINZHI-1);
           ……
        } 
      需要"WEISHU"、"JINZHI-1"这两个参数。第二层循环和最内层的循环体同样需要这两个参数。  
      对于函数的递归调用来说,获得这些参数的的途径可能有三种:函数调用的实参,外部变量,局部static变量。最常用的是第一种,外部变量的办法通常是写不出手的,局部static变量的办法写起来要稍微困难一点。

      修改后的qiongju()函数的定义为

    /*2_穷举.c*/
    
    #include "2_穷举.h"
    
    static void xunhuan(const int ,const int ) ;
    
    extern void qiongju( void )
    {
      
      xunhuan( WEISHU , JINZHI-1 ) ;
    
    }
    
    static void xunhuan( const int gssx /*个数上限*/, 
                         const int sz /*关于哪个数字*/)  
    {
       if( sz > 0 ){
          int i;
          for( i = 0 ; i <= gssx ; i++ ){
             printf("%d个%d " , i , sz );
             xunhuan( gssx - i , sz - 1 );
          }
       }
       else{
          printf("%d个%d " , gssx , sz );
          putchar('\n');//<=>验算<=>记录结果
       }
    }
    

    测试:
    对3进制5位数情况测试,与原来结果一致
    对10进制3位数情况测试,输出正确

    到此,穷举部分基本完成。

  • 相关阅读:
    【转】EDK简单使用流程(3)
    【转】应用 printf 语句格式化输出字符
    【转】[FPGA博客大赛](updated)在xilinx的FPGA系统中scanf函数的使用
    BZOJ 1083 [SCOI2005]繁忙的都市
    BZOJ 2821 分块统计
    BZOJ 1034 [ZJOI2008]泡泡堂BNB
    BZOJ 1029 [JSOI2007]建筑抢修
    BZOJ 1096 [ZJOI2007]仓库建设
    BZOJ 1070 [SCOI2007]修车
    BZOJ 1040 [ZJOI2008]骑士
  • 原文地址:https://www.cnblogs.com/KBTiller/p/2065569.html
Copyright © 2011-2022 走看看