I am a teacher!

导航

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\n",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\n",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\n",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\n",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\n",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\n",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\n",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;

}

posted on 2020-10-22 12:11  aTeacher  阅读(1710)  评论(0编辑  收藏  举报