• C语言程序设计100例之(33):加法算式


    例33    加法算式

    问题描述

    看这个加法算式:

    ☆☆☆ + ☆☆☆ = ☆☆☆

    如果每个五角星代表 1 ~ 9 的不同的数字。

    这个算式有多少种可能的正确填写方法?

    173 + 286 = 459

    295 + 173 = 468

    173 + 295 = 468

    183 + 492 = 675

    以上都是正确的填写法!

            注意:111 + 222 = 333 是错误的填写法!因为每个数字必须是不同的! 也就是说:1~9中的所有数字,每个必须出现且仅出现一次!不包括数字“0”!

            另外,满足加法交换率的式子算两种不同的答案。

    输入格式

            无输入。

    输出格式

            一个整数,表示可能的算式总数。

            (1)编程思路。

            对1-9进行全排列,然后检查每种排列是否满足加法等式要求。

    (2)源程序。

    #include <stdio.h>

    int cnt=0;

    void dfs(int a[10],int pos)

    {

           if(pos>9)

           {

                      int num1=a[1]*100+a[2]*10+a[3];

                      int num2=a[4]*100+a[5]*10+a[6];

                      int num3=a[7]*100+a[8]*10+a[9];

                      if (num1+num2==num3)

                {

     //             printf("%d + %d = %d ",num1,num2,num3);

                    cnt++;

                }

          }

          else

               for(int i=pos;i<=9;i++)

               {

                  int temp = a[i];

                  a[i] = a[pos];

                  a[pos] = temp;

                  dfs(a,pos+1);      // 递归

                  temp = a[i];

                  a[i] = a[pos];

                  a[pos] = temp;

            }

    }

    int main()

    {

        int a[10]={0,1,2,3,4,5,6,7,8,9};

        dfs(a,1);

        printf("%d ",cnt);

        return 0;

    }

    习题33

    33-1  排座位

    问题描述

            有3个A国人、3个B国人和3个C国人坐成一排照相。要求任意两个同一国籍的人不能坐在一起。例如,“A1、B1、A3、B2、C1、B3、C2、A2、C3”就是一种可行的坐法,而“A1、B1、A3、B2、C1、B3、C2、C3、A2”就不满足要求,因为此时坐在第7和第8两个位置的人都是C国人。

            求所有位置安排的不同方案总数?

    输入格式

            无输入。

    输出格式

            一个整数,表示可行的位置安排总数。

         (1)编程思路。

            不妨将9个人分别编号为11、12、13、21、22、23、31、32、33,这样编号后,编号十位数相同的人一定是同一个国籍。对{11,12,13,21,22,23,31,32,33}这9个数进行全排列,然后判断每种排列是否符合要求。

        (2)源程序。

    #include <stdio.h>

    int cnt=0;

    int judge(int a[10])  // 判断同一个国家的两个人是否挨着

    {

        for (int i=1;i<=8;i++)

        {

           if(a[i]/10==a[i+1]/10) return 0;

        }

        return 1;

    }

    void dfs(int a[10],int pos)

    {

        if(pos>9)

           {

               if (judge(a)==1)

            {

                  cnt++;

            }

        }

        else

           for(int i=pos;i<=9;i++)

           {

              int temp = a[i];

              a[i] = a[pos];

              a[pos] = temp;

              dfs(a,pos+1);      // 递归

              temp = a[i];

              a[i] = a[pos];

              a[pos] = temp;

           }

    }

    int main()

    {

        int a[10]={0,11,12,13,21,22,23,31,32,33};

        dfs(a,1);

        printf("%d ",cnt);

        return 0;

    }

    33-2  猜算式

    问题描述

            看下面的算式:□□ x □□ = □□ x □□□ 它表示:两个两位数相乘等于一个两位数乘以一个三位数。如果没有限定条件,这样的例子很多。

            给出限定是:这9个方块,表示1~9的9个数字,不包含0。该算式中1至9的每个数字出现且只出现一次!

    比如:

    46 x 79 = 23 x 158

    54 x 69 = 27 x 138

    54 x 93 = 27 x 186

            请编程,输出所有可能的情况! 注意:左边的两个乘数交换算同一方案,不要重复输出!

    输入格式

            无输入。

    输出格式

            输出所有满足要求的乘法等式,每个等式占1行。

    输入样例

            无输入

    输出样例

    46*79=23*158

    54*69=27*138

    54*93=27*186

    ……  (省略的其他解的情况)

          (1)编程思路1。

            对1-9进行全排列,然后检查每种一次填入9个方框后是否满足乘法等式要求。为了不重复输出,输出时保证左边的两个乘数小数在前,大数在后。

          (2)源程序1。

    #include <stdio.h>

    void dfs(int a[10],int pos)

    {

           if(pos>9)

           {

                      int n1=a[1]*10+a[2];

                      int n2=a[3]*10+a[4];

                      int n3=a[5]*10+a[6];

                      int n4=a[7]*100+a[8]*10+a[9];

                      if (n1<n2 && n1*n2==n3*n4)

                    {

                       printf("%d*%d=%d*%d ",n1,n2,n3,n4);

                   }

            }

            else

               for(int i=pos;i<=9;i++)

               {

                  int temp = a[i];

                  a[i] = a[pos];

                  a[pos] = temp;

                  dfs(a,pos+1);      // 递归

                  temp = a[i];

                  a[i] = a[pos];

                  a[pos] = temp;

            }

    }

    int main()

    {

        int a[10]={0,1,2,3,4,5,6,7,8,9};

        dfs(a,1);

        return 0;

    }

          (3)编程思路2。

            设乘法算式中从左到右的四个数分别为a、b、c、d,用三重循环对a、b、c这三个两位数进行穷举。其中10≤a≤97,a+1≤b≤98, 10≤c≤98。对穷举的每种情况,若a和b的积能整除c,则计算出d,然后判断这4个数中1~9这9个数字是否全部出现。

            为判断数字1~9是否都出现。定义数组int hash[10],其元素初始值全为0,hash[i]=0表示数字i未出现,数字i出现过,置hash[i]=1。

        (4)源程序2。

    #include <stdio.h>

    int main()

    {

           int a,b,c,d,i;

           int hash[10];

           for (a=10; a<=97; a++)

             for (b=a+1; b<=98; b++)

               for (c=10; c<=98; c++)

            {

                if ((a*b)%c==0)

                {

                    d=a*b/c;

                    for (i=0;i<10;i++)

                        hash[i]=0;

                    hash[a/10]=1; hash[a%10]=1;

                    hash[b/10]=1; hash[b%10]=1;

                    hash[c/10]=1; hash[c%10]=1;

                    hash[d/100]=1; hash[d/10%10]=1; hash[d%10]=1;

                    for (i=1;i<=9;i++)

                        if (hash[i]==0) break;

                    if (i>9)

                        printf("%d*%d=%d*%d ",a,b,c,d);

                }

            }

           return 0;

    }

    33-3  三个3位平方数

    问题描述

            将1、2、3、4、5、6、7、8、9九个数字分成三组,每组三个数字构成一个三位数,要求每组中的三位数都组成一个平方数。

            试求出满足要求的3个三位数。

    输入格式

            无输入。

    输出格式

            三个从小到大排列的3位整数。

          (1)编程思路1。

            仿照例33的做法,生成1~9的全排列,再判断全排列的每种情况构成的3个三位数是否都是平方数。

          (2)源程序1。

    #include <stdio.h>

    #include <math.h>

    void dfs(int a[10],int pos)

    {

           if(pos>9)

           {

                int num1=a[1]*100+a[2]*10+a[3];

                int num2=a[4]*100+a[5]*10+a[6];

                int num3=a[7]*100+a[8]*10+a[9];

                int i=(int)sqrt(1.0*num1);

                int j=(int)sqrt(1.0*num2);

                int k=(int)sqrt(1.0*num3);

                if (i*i==num1 && j*j==num2 && k*k==num3)

                {

                   printf("%d  %d  %d ",num1,num2,num3);

                }

          }

         else

               for(int i=pos;i<=9;i++)

               {

                  int temp = a[i];

                  a[i] = a[pos];

                  a[pos] = temp;

                  dfs(a,pos+1);        // 递归

                  temp = a[i];

                  a[i] = a[pos];

                  a[pos] = temp;

            }

    }

    int main()

    {

        int a[10]={0,1,2,3,4,5,6,7,8,9};

        dfs(a,1);

        return 0;

    }

          源程序1运行后输出如下的结果。

    361  529  784

    361  784  529

    529  784  361

    529  361  784

    784  361  529

    784  529  361

            这6个结果按从小到大排列后,本质是一个结果。因此,程序中还需进行去重。

          (3)编程思路2。

            按思路1虽然可以求出3个3位平方数,但并不是这题理想的解法。

            实际上,3位平方数最多有21个(11的平方到31的平方)。因此我们可以先求出所有三位平方数,并且将这些数中出现数字0或存在重复数字的数去掉,例如121、144等。这样的三位平方数一定少于21个,设有cnt个。再在这cnt个数中任意选取3个数进行组合,看每种组合中的3个3位数的数字是否全部不相同,正好1~9每个数字出现一次。

            为判断数字1~9是否都出现。定义数组int hash[10],其元素初始值全为0,hash[i]=0表示数字i未出现,数字i出现过,置hash[i]=1。

        (4)源程序2。

    #include <stdio.h>

    int a[3];

    int cnt=0;

    void dfs(int p[],int pos,int num)

    {

        if (pos==3)

        {

            int hash[10],i;

            for (i=0;i<10;i++)

                hash[i]=0;

            hash[a[0]/100]=1; hash[a[0]/10%10]=1; hash[a[0]%10]=1;

            hash[a[1]/100]=1; hash[a[1]/10%10]=1; hash[a[1]%10]=1;

            hash[a[2]/100]=1; hash[a[2]/10%10]=1; hash[a[2]%10]=1;

            for (i=1;i<=9;i++)

                if (hash[i]==0) break;

            if (i>9)

                 printf("%d %d %d ",a[0],a[1],a[2]);

            return;

        }

        if(3-pos>cnt-num+1) return ;

        for(int i=num;i<cnt;i++)

        {

            a[pos]=p[i];

            dfs(p,pos+1,i+1);

        }

    }

    int main()

    {

        int p[20];

        int i;

        for (i=11;i<=31;i++)

        {

            int a=(i*i)/100;

            int b=(i*i)/10%10;

            int c=(i*i)%10;

            if (a==0 || b==0 ||c==0) continue;

            if (a==b || a==c || b==c) continue;

            p[cnt++]=i*i;

        }

        dfs(p,0,0);

        return 0;

    }

  • 相关阅读:
    组件间通信
    Android抓包方法(一)之Fiddler代理
    汉字转拼音
    post请求参数问题
    post请求参数设置
    swagger
    IfcPresentationDefinitionResource(介绍定义资源)
    Java计算两个日期之间的时间差(毫秒数)
    IfcPresentationAppearanceResource(外观定义资源)
    IfcMeasureResource(度量资源)
  • 原文地址:https://www.cnblogs.com/cs-whut/p/13857502.html
Copyright © 2020-2023  润新知