练习76

  1. /*******************************************************************************
  2.   76. (省刻度尺问题)给定长度为 L 的直尺, L 为整数, 且L≤40. 为了能一次直接
  3.  量出  1,2,...,L 的各种长度, 该尺内部至少要有多少条刻度 ?  请输出最少刻度
  4.  数( 不含两端点)及每个刻度的位置. 测量长度时可利用两端点, 其位置分别为 0,
  5.  L.
  6.     输入: 由键盘输入 L.
  7.     输出: 用文本文件按以下格式输出结果(文件名: ANS2.TXT):
  8.       第 1 行: S ( 最少刻度数 )
  9.       第 2 行: 尺内 S 个刻度的位置
  10.       第 3 行至第 L+2 行: 每行输出 3 个用空格隔开的整数 t m n, 其中
  11.  1≤t≤L 为要测量的各长度, m,n 依次为该长度的起止刻度 (m<n).
  12.     例: 如果 L=6, 则一个正确的输出是:
  13.        2
  14.        1 4                    提示:  (1) 最少刻度数 S 应满足:
  15.        1 0 1                     C[S+2,2]=(S+2)*(S+1)/2≥L.
  16.        2 4 6                         (2) 除两端点外, 第一个刻度可取为
  17.        3 1 4                     A[1]=1, 第二个刻度可在 1, L-2, L-1 这
  18.        4 0 4                     三个数中选取.
  19.        5 1 6
  20.        6 0 6
  21.   *****************************************************************************/
  22. /*检验程序
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #define N 46
  26. #define M 12
  27. int kd[M];
  28. int checked(int kd[])
  29. {
  30.     int i,j;
  31.     int ch[N];
  32.     for(i=0; i<N; i++)
  33.         ch[i] = 0;
  34.     for(i=0; i<M-1; i++)
  35.         for(j=i+1; j<M; j++)
  36.         {
  37.             ch[kd[j]-kd[i]-1] = 1;
  38.         }
  39.     for(i=0; i<N; i++)
  40.     {
  41.         if(!ch[i])
  42.             return 0;
  43.     }
  44.     return 1;
  45. }
  46. void comb(int a[], int n, int r)
  47. {
  48.     if(r==0)
  49.     {
  50.         int i;
  51.         for(i=2; i<M-1; i++)
  52.             kd[i] = a[i-2]+1;
  53.         if(checked(kd))
  54.         {
  55.             for(i=0; i<M; i++)
  56.             {
  57.                 printf("%d ",kd[i]);
  58.             }
  59.             printf("/n");
  60.             _exit(-1);
  61.         }
  62.     }
  63.     else if(n>=r)
  64.     {
  65.         a[r-1] = n;
  66.         comb(a,n-1,r-1);
  67.         comb(a,n-1,r);
  68.     }
  69. }
  70. void main()
  71. {
  72.     int a[M-3];
  73.     kd[0] = 0;
  74.     kd[1] = 1;
  75.     kd[M-1] = N;
  76.     
  77.     comb(a,N-2,M-3);
  78. }
  79. */
  80. #include <stdio.h>
  81. #include <stdlib.h>
  82. #include <malloc.h>
  83. typedef struct
  84. {
  85.     int s;
  86.     int t;
  87. } ST;
  88. int M;
  89. int L;
  90. int *kd;
  91. int *chk;
  92. int *comb;
  93. ST *st;
  94. //检验合法性
  95. int checked()
  96. {
  97.     int i,j;
  98.     
  99.     //组合转化为刻度
  100.     for(i=2; i<M-2; i++)
  101.             kd[i] = comb[i-2]+2;
  102.     //检查数组初时化为0,检测该刻度是否能表示
  103.     for(i=0; i<L; i++)
  104.         chk[i] = 0;
  105.     
  106.     for(i=0; i<M-1; i++)
  107.     {
  108.         for(j=i+1; j<M; j++)
  109.         {
  110.             chk[kd[j]-kd[i]-1] = 1;
  111.         }
  112.     }
  113.     //判断刻度是否能表示,如果有一个不能表示,返回不合法
  114.     for(i=0; i<L; i++)
  115.     {
  116.         if(!chk[i])
  117.         {
  118.             return 0;
  119.         }
  120.     }
  121.     //合法
  122.     //保存表示值
  123.     for(i=0; i<M-1; i++)
  124.     {
  125.         for(j=i+1; j<M; j++)
  126.         {
  127.             st[kd[j]-kd[i]-1].s = kd[i];
  128.             st[kd[j]-kd[i]-1].t = kd[j];
  129.         }
  130.     }
  131.     //返回合法
  132.     return 1;
  133. }
  134. //生成第一个组合
  135. int FirstComb(int r)
  136. {
  137.     int i;
  138.     if(r == 0)
  139.         return 0;
  140.     for(i=0; i<r; i++)
  141.         comb[i] = i;
  142.     return 1;
  143. }
  144. //生成下一组合
  145. int NextComb(int n, int r)
  146. {
  147.     int i,j;
  148.     i = r - 1;
  149.     while (comb[i] == n - r + i) 
  150.     {
  151.         i--;
  152.     }
  153.     if(i<0) return 0;
  154.     comb[i] = comb[i] + 1;
  155.     for (j = i + 1; j < r; j++) 
  156.     {
  157.         comb[j] = comb[i] + j - i;
  158.     }
  159.     return 1;
  160. }
  161. //显示结果
  162. void PrintRs()
  163. {
  164.     int i;
  165.     printf("%d/n",M-2);
  166.     for(i=1; i<M-1; i++)
  167.         printf("%d ",kd[i]);
  168.     printf("/n");
  169.     for(i=0; i<L; i++)
  170.     {
  171.         printf("%2d %3d %3d/n",i+1,st[i].s,st[i].t);
  172.     }
  173.     printf("/n");
  174. }
  175. //main函数
  176. void main()
  177. {
  178.     printf("请输入刻度尺的量程L:");
  179.     scanf("%d",&L);
  180.     //求出最小刻度数
  181.     for(M=2; (M-1)*M<2*L; M++);
  182.     //检验数组
  183.     chk = (int*)malloc(L*sizeof(int));
  184.     //刻度表示值数组
  185.     st = (ST*)malloc(L*sizeof(ST));
  186. L1: //刻度值数组
  187.     kd = (int*)malloc(M*sizeof(int));
  188.     kd[0] = 0;
  189.     kd[M-1] = L;
  190.     if(M == 2)
  191.     {
  192.         if(checked())
  193.         {
  194.             PrintRs();
  195.             goto L3;
  196.         }
  197.         goto L2;
  198.     }
  199.     else if(M == 3)
  200.     {
  201.         kd[1] = 1;
  202.         if(checked())
  203.         {
  204.             PrintRs();
  205.             goto L3;
  206.         }
  207.         goto L2;
  208.     }
  209.     else if(M == 4)
  210.     {
  211.         kd[1] = 1;
  212.         kd[M-2] = L-1;
  213.         if(checked())
  214.         {
  215.             PrintRs();
  216.             goto L3;
  217.         }
  218.         kd[M-2] = L-2;
  219.         if(checked())
  220.         {
  221.             PrintRs();
  222.             goto L3;
  223.         }
  224.         goto L2;
  225.     }
  226.     else if(M > 4)
  227.     {
  228.         kd[1] = 1;
  229.         kd[M-2] = L-1;
  230.         comb = (int*)malloc((M-4)*sizeof(int));
  231.         if(FirstComb(M-4))
  232.         {
  233.             do
  234.             {
  235.                 if(checked())
  236.                 {
  237.                     PrintRs();
  238.                     goto L3;
  239.                 }
  240.             }while(NextComb(L-3, M-4));
  241.         }
  242.         kd[M-2] = L-2;
  243.         if(FirstComb(M-4))
  244.         {
  245.             do
  246.             {
  247.                 if(checked())
  248.                 {
  249.                     PrintRs();
  250.                     goto L3;
  251.                 }
  252.             }while(NextComb(L-4, M-4));
  253.         }
  254.         goto L2;
  255.     }
  256. L2: 
  257.     free(kd);
  258.     free(comb);
  259.     M++;
  260.     goto L1;
  261. L3: 
  262.     free(kd);
  263.     free(comb);
  264.     free(st);
  265.     
  266.     free(chk);
  267. }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值