免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: DNFCF
打印 上一主题 下一主题

[算法] 变态的算法题 [复制链接]

论坛徽章:
0
71 [报告]
发表于 2011-05-17 12:11 |只看该作者
1_MAIN_type.h


  1. #ifndef MAIN_T_H
  2. #define MAIN_T_H
  3.     //NOTHING
  4. #endif // MAIN_T_H

复制代码


1_MAIN_function.h


  1. #ifndef MAIN_F_H
  2. #define MAIN_F_H
  3.     #include "1_MAIN_type.h"      
  4.     #include "2_数字组合_function.h"  //zuhe_sz()及参数
  5.     #include "5_处理结果_function.h"  //shuchu_jg()
  6.     #include <stdlib.h>               //system()
  7.      
  8. #endif // MAIN_F_H

复制代码


1_MAIN.c

  1. /*
  2.   Name:花朵数问题
  3.   Author: 键盘农夫
  4.   Date: 17-05-11
  5.   Description: 一个一般性解法,
  6.                适用其他进制(<=10)、其他位数的花朵数求解
  7. */
  8. #include "1_MAIN_function.h"
  9. #define ANY 0
  10. int main( void )
  11. {
  12.     zuhe_sz( ZHUNBEI , ANY );    //进行数字组合<=>验算<=>存储结果
  13.            //第一个实参为ZHUNBEI时,第二个实参没有用处
  14.     shuchu_jg();                 //输出结果,释放内存   
  15.     system("PAUSE");
  16.     return 0;
  17. }
  18. #undef ANY
  19. /*
  20. 注:稍微修改一下输出的函数shuchu(),程序也适合10以上进制
  21. */

复制代码

论坛徽章:
0
72 [报告]
发表于 2011-05-17 12:13 |只看该作者
本帖最后由 KBTiller 于 2011-05-18 11:12 编辑

2_数字组合_type.h


  1. #ifndef ZUHE_T_H
  2. #define ZUHE_T_H
  3.     #include "3_组合验算_type.h"      
  4.     #include "0_问题.h"
  5. #endif // ZUHE_T_H

复制代码


2_数字组合_function.h


  1. #ifndef ZUHE_F_H
  2. #define ZUHE_F_H
  3.     #include "2_数字组合_type.h"
  4.     #include "3_组合验算_function.h"   
  5.     #include "4_大数运算_function.h"      
  6.       
  7.     extern void zuhe_sz( const int , const int );
  8.     //zuhe_sz()的两个特殊参数
  9.         #define ZHUNBEI   JINZHI
  10.         #define WANCHENG  0
  11. #endif // ZUHE_F_H

复制代码


2_数字组合.c


  1. #include "2_数字组合_function.h"
  2. //求"WEISU位数"的各种数字组合
  3. //sz:某一数字,gs:该数字可能选择的最大个数
  4. //sz: ZHUNBEI 进行必要准备
  5. //sz: WANCHENG 组合完成(可以确定0的个数时)
  6. extern void zuhe_sz( const int sz , const  int gs )
  7. {
  8.     static SHUZI_GESHU_t sj_gs , //实际的个数
  9.                          gs_sx ; //个数的上限
  10.    
  11.     switch ( sz ) {
  12.         case  ZHUNBEI:
  13.                       jisuan_zhunbei( & gs_sx );   //计算准备
  14.                       zuhe_sz ( sz - 1 , WEISHU ) ;
  15.                       qing0( & gs_sx );            //对 gs_sx清0                     
  16.                       break;
  17.         default      :  //尝试某数字(sz)的各种可能的数目(i)
  18.                       {
  19.                           int i ;
  20.                           for ( i =  0 ;
  21.                                 i <= ( (gs < gs_sx[sz]) ? gs : gs_sx[sz] ) ;
  22.                                 i ++  ){
  23.                               sj_gs [ sz ] = i ;
  24.                               zuhe_sz ( sz - 1 , gs - i ) ; //下一个数字
  25.                               sj_gs [ sz ] = 0 ;
  26.                           }
  27.                       }                        
  28.                       break;
  29.         case WANCHENG:   
  30.                       sj_gs [ sz ] = gs  ;         //0的个数  
  31.                       jianyan( &sj_gs )  ;         //对数字组合验算
  32.                       sj_gs [ sz ] = 0   ;            
  33.                       break;
  34.     }                     
  35. }

复制代码

论坛徽章:
0
73 [报告]
发表于 2011-05-17 12:15 |只看该作者
3_组合验算_type.h


  1. #ifndef YANSUAN_T_H
  2. #define YANSUAN_T_H
  3.     #include "0_问题.h"
  4.     #include "6_常用.h"   
  5.     #include "4_大数运算_type.h"        
  6.     typedef int     SHUZI_GESHU_t[JINZHI]   ;   //描述各个数字出现个数的类型
  7.     // 0的个数,1的个数……JINZHI-1的个数     
  8. #endif // YANSUAN_T_H

复制代码


3_组合验算_function.h


  1. #ifndef YANSUAN_F_H
  2. #define YANSUAN_F_H
  3.     #include "3_组合验算_type.h"      
  4.    
  5.     #include "4_大数运算_function.h"         
  6.     #include "5_处理结果_function.h"         
  7.          
  8.     extern void jisuan_zhunbei( SHUZI_GESHU_t * );
  9.     extern void qing0  ( SHUZI_GESHU_t * )  ;
  10.     extern void jianyan( SHUZI_GESHU_t * )  ;
  11. #endif // YANSUAN_F_H

复制代码


3_组合验算.c


  1. #include "3_组合验算_function.h"   
  2. static DASHU_t sjb[JINZHI][WEISHU]; //数据表   
  3. //////         1*0^N,2*0^N,……WEISHU*0^N
  4. //////         1*1^N,2*1^N,……WEISHU*1^N
  5. //////         1*2^N,2*2^N,……WEISHU*2^N
  6. //////         ……
  7. //////         1*9^N,2*9^N,……WEISHU*9^N   
  8. //////================================================
  9. //检验构成组合的各个数字的N次方之和的数字组合
  10. //是否与原来的组合一致
  11. extern void jianyan( SHUZI_GESHU_t * p_zhsm )
  12. {
  13.     DASHU_t he ;
  14.     fuzhi ( & he , 0 ) ;  //初值为0
  15.     int i ;
  16.     for( i = 1; i < GESHU(sjb) ; i++){ //i=1, 0的N次幂不用加
  17.        if ( (* p_zhsm)[i] == 0 )           //某数字不出现
  18.            continue ;   
  19.        jiaru( & he , sjb[i] + (( * p_zhsm )[i] - 1)  ); // 求和
  20.     }
  21.    
  22.     if(  chaoguo_ws ( & he ) == SHI
  23.       || bugou_ws   ( & he ) == SHI  )     //位数不符合
  24.        return ;
  25.    
  26.     if ( xiangtong ( & he , p_zhsm ) == FOU )//和的组合与原来的组合不同
  27.         return ;         
  28.    
  29.     jilu_jg( &he );
  30. }
  31. //求各个数字的N次方及其整数倍(1,2,……WEISHU倍)
  32. //同时求出各个数字出现次数的上限存入 * p_zhsx
  33. extern void jisuan_zhunbei( SHUZI_GESHU_t * p_zhsx )
  34. {
  35.     int hang , lie ;
  36.    
  37.     for ( hang = 0 ; hang < GESHU( sjb ) ; hang++ ){
  38.         
  39.         qiu_mi ( sjb[hang]  , hang , N  ) ;     //求i的N次幂
  40.         
  41.         for ( lie = 1 ; lie < GESHU( sjb[hang] ) ; lie ++  ) { //WEISHU
  42.             cheng ( sjb[hang] + lie    , sjb[hang]   , lie + 1 ) ;
  43.             
  44.             if ( chaoguo_ws ( sjb[hang] + lie ) == SHI ) //结果超过WEISHU
  45.                 break ;   
  46.         }   
  47.         (* p_zhsx)[hang] = lie  ;    // 某数字出现次数的上限值
  48.     }
  49. }
  50. extern void qing0( SHUZI_GESHU_t * p_zhsx )
  51. {
  52.     int *p = * p_zhsx ;
  53.     while ( p < * ( p_zhsx + 1 ))
  54.         *p++ = 0 ;
  55. }

复制代码

论坛徽章:
0
74 [报告]
发表于 2011-05-17 12:17 |只看该作者
4_大数运算_type.h


  1. #ifndef DASHU_T_H
  2. #define DASHU_T_H
  3.     #include "0_问题.h"
  4.     #include "6_常用.h"
  5.     #include "3_组合验算_type.h"
  6.     typedef int DASHU_t[WEISHU] ; //大数类型
  7.    
  8. #endif // DASHU_T_H

复制代码


4_大数运算_function.h


  1. #ifndef DASHU_F_H
  2. #define DASHU_F_H
  3.     #include "4_大数运算_type.h"
  4.    
  5.     #include <stdio.h>
  6.     #include "3_组合验算_function.h"   
  7.         
  8.     extern void qiu_mi ( DASHU_t * const , const int , int  ) ;
  9.     extern void fuzhi  ( DASHU_t * const , const int ) ;
  10.     extern void cheng  ( DASHU_t * const , DASHU_t * const , const int );
  11.     extern void jiaru  ( DASHU_t * const ,  DASHU_t * const );
  12.     extern void shuchu ( DASHU_t * const );
  13.     extern void copy_ds( DASHU_t * const , DASHU_t * const ) ;
  14.     extern SF   xiaoyu     ( DASHU_t * const , DASHU_t * const ) ;
  15.     extern SF   chaoguo_ws ( DASHU_t * const ) ;
  16.     extern SF   bugou_ws   ( DASHU_t * const ) ;
  17.     extern SF   xiangtong  (  DASHU_t * const  ,  SHUZI_GESHU_t * const ) ;
  18. #endif // DASHU_F_H

复制代码

4_大数运算.c


  1. #include "4_大数运算_function.h"
  2. extern  void shuchu(  DASHU_t * const p_ds )
  3. {
  4.     int *w = *p_ds , *t = *(p_ds+1) -1;
  5.     int i;
  6.    
  7.     while( t > w && *t == 0) //前面的0不输出
  8.        t--;  
  9.    
  10.     for ( i = t - w ; i >= 0 ; i-- )
  11.        printf("%d" , w[i]);
  12.     putchar('\n');
  13. }
  14. extern void copy_ds ( DASHU_t * const p_zd, DASHU_t * const p_qd )
  15. {
  16.     int i ;
  17.     for (i = 0 ; i < GESHU(*p_zd) ; i++ )
  18.         (*p_zd)[i] = (*p_qd)[i] ;
  19. }
  20. //判断*p_he的组合是否与*p_szzh相同
  21. SF xiangtong ( DASHU_t * const p_he ,  SHUZI_GESHU_t * const p_szzh )
  22. {
  23.     SHUZI_GESHU_t szgs ;
  24.     int i ;
  25.     qing0  ( & szgs ) ;
  26.     for (i = 0 ; i < GESHU(*p_he) ; i++ )
  27.         szgs[(*p_he)[i]]++;
  28.    
  29.     for(i=0;i<GESHU(szgs);i++)
  30.         if(szgs[i]!=((*p_szzh)[i]))
  31.             return FOU ;
  32.         
  33.     return SHI;
  34. }
  35. //进位
  36. static void jinwei( DASHU_t * const p_ds)
  37. {
  38.     int *q = *p_ds ;
  39.     while ( q < *( p_ds + 1) - 1 ){
  40.         * ( q + 1 ) += * q / JINZHI ;
  41.         * q++ %= JINZHI ;
  42.     }   
  43. }
  44. //小于
  45. extern SF xiaoyu  ( DASHU_t * const p_ds1 , DASHU_t * const p_ds2 )
  46. {
  47.     int i;
  48.     for( i = GESHU(*p_ds1) - 1 ; i >= 0 ; i -- ){
  49.         if( (*p_ds1)[i]<(*p_ds2)[i] )
  50.             return SHI ;
  51.         if( (*p_ds1)[i]>(*p_ds2)[i] )
  52.             return FOU ;
  53.     }
  54.     return FOU ;   
  55. }
  56. //将*p_js累加入*p_he
  57. extern void jiaru( DASHU_t * const p_he ,  DASHU_t * const p_js)
  58. {
  59.     int i;
  60.     for(i=0;i<GESHU(*p_he);i++)
  61.         (*p_he)[i] += (*p_js)[i];
  62.         
  63.     jinwei(p_he) ;
  64. }
  65. //判断是否超过WEISHU
  66. extern SF chaoguo_ws ( DASHU_t * const p_ds )
  67. {
  68.     if( p_ds[1][-1] >= JINZHI ){
  69.         return SHI ;
  70.     }
  71.     return FOU;
  72. }
  73. //判断是否位数不到WEISHU
  74. extern SF bugou_ws ( DASHU_t * const p_ds )
  75. {
  76.     if( p_ds[1][-1] == 0 )
  77.         return SHI ;
  78.     return FOU;
  79. }
  80. //cs2*(*p_cs1)=>(*p_ji)
  81. extern void cheng ( DASHU_t * const p_ji , DASHU_t * const p_cs1 , const int cs2)
  82. {
  83.    int *p = *p_ji ,*q = *p_cs1;
  84.    while ( p < * ( p_ji + 1) )
  85.         *p++ = *q++ * cs2 ;
  86.    
  87.    //进位
  88.    jinwei( p_ji );   
  89. }
  90. //求i的n次幂,放在 * p_ds 中
  91. extern void qiu_mi ( DASHU_t * const p_ds , const int i , int  n  )
  92. {
  93.     fuzhi ( p_ds , i ) ;
  94.     while ( --n > 0 )
  95.         cheng ( p_ds , p_ds , i);
  96. }
  97. //赋值,大于JINZHI的数也可以
  98. extern  void fuzhi ( DASHU_t * const p_ds , const int i )
  99. {
  100.     int *q = *p_ds ;
  101.     *q = i ;
  102.     while ( q < *( p_ds + 1) - 1){
  103.         * ( q + 1 ) = * q / JINZHI ;
  104.         * q++ %= JINZHI ;
  105.     }
  106. }

复制代码

论坛徽章:
0
75 [报告]
发表于 2011-05-17 12:19 |只看该作者
5_处理结果_type.h


  1. #ifndef JIEGUO_T_H
  2. #define JIEGUO_T_H

  3.    
  4.     #include "0_问题.h"
  5.     #include "4_大数运算_type.h"
  6.     typedef struct JD{
  7.                       DASHU_t ds   ;  //大数
  8.                       struct JD *xyg ;//下一个
  9.                      } JIEDIAN_t ;      //节点类型
  10.     typedef JIEDIAN_t *TOU_t  ;         //头类型
  11. #endif // JIEGUO_T_H

复制代码

5_处理结果_function.h

  1. #ifndef JIEGUO_F_H
  2. #define JIEGUO_F_H
  3.     #include "5_处理结果_type.h"
  4.    
  5.     #include "4_大数运算_function.h"      
  6.     #include <stdio.h>
  7.     #include <stdlib.h>
  8.         
  9.     extern void jilu_jg( DASHU_t * );
  10.     extern void shuchu_jg ( void );
  11.    
  12. #endif // JIEGUO_F_H

复制代码

5_处理结果.c


  1. #include "5_处理结果_function.h"
  2. static TOU_t tou = NULL ;
  3. static void jia_jd ( TOU_t ,TOU_t *);
  4. static void shifang_nc(TOU_t);
  5. static void shifang_nc( TOU_t p )
  6. {
  7.     TOU_t q  ;
  8.     if( p == NULL )
  9.         return ;
  10.    
  11.     q = p->xyg ;
  12.     free(p);
  13.     shifang_nc( q );
  14. }
  15. extern void jilu_jg( DASHU_t * p_ds )
  16. {
  17.     TOU_t p_jd ;
  18.     if( (p_jd = malloc( sizeof (JIEDIAN_t )) ) == NULL ){
  19.         shifang_nc( tou );
  20.         puts("无法记录结果,程序退出");
  21.         exit ( ! EXIT_SUCCESS ) ;
  22.     }
  23.    
  24.     copy_ds ( & p_jd->ds  , p_ds ) ;   //复制
  25.     jia_jd ( p_jd , & tou );           //加入链表(p_jd,tou)
  26. }
  27. //按照一定次序加入节点
  28. static void jia_jd ( TOU_t  xjd, TOU_t  *p_xyg  )
  29. {
  30.     if( *p_xyg == NULL ||
  31.         ( xiaoyu ( & xjd -> ds , &(*p_xyg)->ds )) == SHI ){/* 小于 */
  32.         xjd->xyg = *p_xyg ;
  33.         *p_xyg = xjd ;
  34.         return ;
  35.     }
  36.     jia_jd ( xjd  , &(*p_xyg)->xyg ) ;
  37. }
  38. //输出结果,之后释放内存
  39. extern void shuchu_jg( void )
  40. {
  41.     TOU_t temp = tou ;
  42.     while ( temp != NULL ){
  43.         shuchu(&temp->ds);
  44.         temp = temp->xyg ;
  45.     }   
  46.     shifang_nc( tou );   
  47.     tou = NULL ;
  48. }

复制代码

论坛徽章:
0
76 [报告]
发表于 2011-05-17 12:21 |只看该作者
6_常用.h


  1. //我编程常用的成语和俚语
  2. #ifndef CHANGYONG_H
  3. #define CHANGYONG_H
  4.     typedef enum { FOU , SHI } SF ;
  5.    
  6.     #define GESHU(A) ((sizeof (A)) / (sizeof (*(A))) )
  7.    
  8. #endif // CHANGYONG_H

复制代码

论坛徽章:
0
77 [报告]
发表于 2011-05-17 12:35 |只看该作者
从蔡万钊、A.com、koolcoy (娶妻求贤)网友的发言中受到了许多启发,在此致谢!

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:45
78 [报告]
发表于 2011-05-17 14:26 |只看该作者
好多年没看过用拼音写的程序了,怎么看怎么囧,有空了再来研究{:3_196:}

论坛徽章:
3
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:58:11数据库技术版块每日发帖之星
日期:2015-08-30 06:20:00
79 [报告]
发表于 2011-05-17 20:30 |只看该作者
回复 70# KBTiller


    我是 AMD64 的 Gentoo 系统。

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:45
80 [报告]
发表于 2011-05-18 10:31 |只看该作者
昨晚想了一下这个问题,有这么一个优化方法:
将1^21 * 1, 1^21 * 2, 1^21 * 3 ... 1^21 * 21, 2^21 * 1, 2^21 * 2 ... 2^21 * 21, .... 9^21 * 21一共189个数保存起来。于是原问题抓换成从这189个数中选最多9个数出来,使得他们的和满足一定的条件。整个问题的解空间小于21^9 ,这个数字大概是5000亿,采用深搜,再根据位数为21这个条件剪一下枝,最终的解空间应该不会超过100亿。

这种算法的复杂度是O(N^9),而不是O(9^N),N为位数。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP