zoukankan      html  css  js  c++  java
  • C语言-回溯例4

    1,问题提出 日本数学家桥本吉彦教授于1993年10月在我国山东举行的中日美三国数学教育研讨会上向与会者提出以下填数趣题: 把1,2,...,9这9个数字填入下式的九个方格中(数字不得重复),使下面的分数等式成立

     

    桥本教授当即给出了一个解答。这一分数式填数趣题究竟共有多少个解答? 试求出所有解答。(等式左边两个分数交换次序只算一个解答)。

    2,回溯算法设计
    设置a数组,式中每一□位置用一个数组元素来表示 .
    为判断数字是否重复,设置中间变量g:若出现某两数字相同(即a(i)=a(k))或a(1)>a(4),则赋值g=0(重复标记)。
    首先从a(1)=1开始,逐步给a(i)(1≤i≤9)赋值,每一个a(i)赋值从1开始递增至9。直至a(9)赋值,判断:
    若i=9,g=1,等式同时满足,则为一组解,用n统计解的个数后,格式打印输出这组解。
    若i<9 且g=1,表明还不到九个数字,则下一个a(i)从1开始赋值继续。
    若a(9)=9 ,则返回前一个数组元素a(8)增1 赋值(此时,a(9)又从1开始)再试。若a(8)=9 ,则返回前一个数组元素a(7)增1 赋值再试。
    依此类推,直到a(1)=9时,已无法返回,意味着已全部试毕,求解结束。

    3,代码实现

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 int main()
     5 {
     6     int flag;//设置标志位
     7     int k,i,sum,x,y,z;
     8     int a[10];
     9     i=1;
    10     a[i]=1;//附初始值
    11     sum=0;//记录解得个数
    12     while(1)
    13     {
    14         flag=1;
    15         for(k=i-1;k>=1;k--)
    16         {
    17             if(a[k]==a[i])
    18             {
    19                 flag=0;//不满足条件,改变标志位
    20             }
    21         }
    22         if(flag&&i==9)//得到一组解,输出
    23         {
    24             sum++;
    25             x=a[2]*10+a[3];
    26             y=a[5]*10+a[6];
    27             z=a[8]*10+a[9];
    28             if((x*a[4]*a[7]+y*a[1]*a[7])==(z*a[1]*a[4]))
    29             {
    30                 printf("first1:%d%d/%d+%d%d/%d=%d%d/%d
    ",a[2],a[3],a[1],a[5],a[6],a[4],a[8],a[9],a[7]);
    31                 printf("first2:%d/%d+%d/%d=%d/%d",x,a[1],y,a[4],z,a[7]);
    32                 printf("
    ");
    33             }
    34         }
    35         if(flag&&i<9)
    36         {
    37             i++;
    38             a[i]=1;
    39             continue;
    40         }
    41         while(a[i]==9&&i>1)i--;//回溯
    42         if(a[i]==9&&i==1)
    43         {
    44             break;
    45         }
    46         else
    47         {
    48             a[i]++;//寻找下一条路径
    49         }
    50     }
    51     printf("The sum is %d",sum);
    52     return 0;
    53 }

    运行结果:

    4,说明

    上面代码实现的是题目要求的颠倒,即上面是两个空,下面是一个空,要实现题目要求,只需将将x,y,z改变一下即可。

    另外如果左面的两个数次序颠倒算一次的话,只需在约束条件中增加一个条件即可:a[1]>a[4];

  • 相关阅读:
    codevs1231 最优布线问题
    P1352 没有上司的舞会——树形DP入门
    codevs1961 躲避大龙
    codevs2833 奇怪的梦境
    linux 内存管理——内核的shmall 和shmmax 参数
    删除共享内存后key为0x00000000的问题
    redis命令之lrange
    vim配置vimrc详解
    chmod chgrp chown
    localtime和localtime_r
  • 原文地址:https://www.cnblogs.com/xiaojingang/p/3758114.html
Copyright © 2011-2022 走看看