博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【算法】算法中的趣味数学(一)
阅读量:6860 次
发布时间:2019-06-26

本文共 4816 字,大约阅读时间需要 16 分钟。

小续

   以下是我收集的一些有趣的计算实例,希望能够提高读者的编程水平及分析问题/解决问题的能力

---------------------------------------------

马克思手稿中的数学题

  马克思手稿中有一道趣味数学题:有30个人,其中有男人、女人和小孩,在一家饭馆吃饭共花了50先令。若每个男人花3先令,每个女人花2先令,每个小孩花1先令。问男人、女人和小孩各有几人?

   实例解析:

   设x,y,z分别代表男人、女人和小孩的人数。按题目要求,可得到下面方程:

                  x + y + z = 30                (1)

                  3x + 2y + z = 50              (2)

   (2)-(1)可得

                  2x + y = 20                  (3)

   由(3)式可知,x的变化范围是1~10 (根据题意,男人、女人、小孩都有,故x、y、z都不能为0)。  

    程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
int 
main()
{
    
int 
x,y,z,count = 0;
    
clrscr();
    
puts
(
" >> The solutions are:"
);
    
printf
(
"  No.      Men     Women   Children\n"
);
    
printf
(
"--------------------------------\n"
);
    
for
(x = 1; x <= 10; x++)
    
{
        
y = 20 - 2*x;                   
//由(3)式求y
        
z = 30 – x - y;                
//由(1)式求z
        
if
(3*x + 2*y + z == 50 && y && z) 
//当前组合是否满足式(2)
        
printf
(
" <%2d> | %2d | %2d | %2d\n"
, ++count,x,y,z);
    
}
    
printf
(
"--------------------------------\n"
);
    
printf
(
" Press any key to quit..."
);
    
getch();
    
return 
0;
}


配对新郎和新娘

  3对情侣参加婚礼,3个新郎为A、B、C,3个新娘为X、Y、Z。有人不知道谁和谁结婚,于是询问了6位新人中的3位,但听到的回答是这样的:A说他将和X结婚;X说她的未婚夫是C;C说他将和Z结婚。这人听后知道他们在开玩笑,全是假话。请编程确认谁和谁是一对。

  实例解析:

  分表将A、B、C用1,2,3表示,将X和A结婚表示为“X == 1”,将Y不与A结婚表示为“Y !=1”,按题目叙述可写出下列表达式:

        X != 1           A不与X结婚

        X != 3           X的未婚夫不是C

        Z != 3           C不与Z结婚

  穷举满足以上条件所有可能的情况。

  程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
int 
main()
{
    
int 
x,y,z;
    
puts
(
" >> The solutions are:"
);
    
printf
(
"-------------------------------------\n"
);
    
for
(x = 1; x <= 3; x++)          
//穷举x的全部可能配偶
        
for
(y = 1; y <= 3; y++)        
//穷举y的全部可能配偶
            
for
(z = 1; z <= 3; z++)      
//穷举z的全部可能配偶
                
if
(x!=1 && x!=3 && z!=3 && x!=y && x!=z && y!=z)
                
{
                    
printf
(
"X will marry to %c.\n"
'A'
+x-1);
                    
printf
(
"Y will marry to %c.\n"
'A'
+y-1);
                    
printf
(
"Z will marry to %c.\n"
'A'
+z-1);
                
}
    
printf
(
"--------------------------------------\n"
);
    
printf
(
" Press any key to quit..."
);
    
getch();
    
return 
0;
}


分糖果

  10个小孩围成一圈分糖果,老师分给第一个小孩10块,第二个小孩2块,第三个小孩8块,第四个小孩22块,第五个小孩16块,第六个小孩4块,第七个小孩10块,第八个小孩6块,第九个小孩14块,第十个小孩20块。然后所有的小孩同时将手中的糖分一半给右边的小孩,糖块为奇数的可向老师再要一块。问这样的操作经过几次,大家手中的糖一样多?每人有多少块糖?

  实例解析:

  分糖过程是一个机械的重复过程。算法完全可以按照描述的过程进行模拟。

  程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdio.h>
void 
print(
int 
s[]);
int 
judge(
int 
c[]);
int 
j = 0;
int 
main()
{
    
int 
sweet[10] = {10,2,8,22,16,4,10,6,14,20};
    
int 
i, t[10], k;
    
printf
(
"Child No.  1   2  3  4  5  6  7  8  9  10\n"
);
    
printf
(
"-------------------------------------\n"
);
    
printf
(
"Round No.|\n"
);
    
print(sweet);               
//输出每个人手中糖的块数
    
while
(judge(sweet))
    
{      
//若不满足要求则继续进行循环
        
for
(i = 0; i < 10; i++)
            
t[i] = sweet[i] = sweet[i]/2; 
//每个人手中的糖分成两半
        
for
(k = 0; k < 9; k++)
        
{
            
sweet[k+1] = sweet[k+1] + t[k]; 
//分出的一半糖给右边
            
if
(sweet[k+1]%2!=0)
                
sweet[k+1]++;
        
}
        
sweet[0] += t[9];
        
if
(sweet[0]%2!=0)
            
sweet[0]++;
        
print(sweet);             
//输出当前每个孩子中手中的糖数
    
}
    
printf
(
"-------------------------------------\n"
);
    
printf
(
"\n Press any key to quit..."
);
    
getch();
    
return 
0;
}
int 
judge(
int 
c[])
{
    
int 
i;
    
for
(i = 0; i < 10; i++)   
//判断每个孩子手中的糖是否相同
    
if
(c[0] != c[i])
            
return 
1;          
//不相同返回 1
    
return 
0;
}
  
void 
print(
int 
s[])      
//输出数组中每个元素的值
{
    
int 
k;
    
printf
(
"      <%2d> | "
, j++);
    
for
(k = 0; k < 10; k++)
        
printf
(
"%4d"
, s[k]);
    
printf
(
"\n"
);
}


波瓦松的分酒问题

  法国著名数学家波瓦松(Poison)在青年时代研究过一个有趣的数学问题:某人有12品脱的啤酒一瓶,想从中倒出6品脱,但他没有6品脱的容器,仅有一个8品脱和5品脱的容器,怎样才能将啤酒分成两个6品脱呢?

  实例解析:

  将12品脱酒用8品脱和5品脱的空瓶平分,可以抽象为解不定方程:

               8x - 5y = 6

  其意义是:从12品脱的瓶中向8品脱的瓶中倒x次,并且将5品脱瓶中的酒向12品脱的瓶中倒y次,最后在12品脱的瓶中剩余6品脱的酒。

  分别用a,b,c代表12品脱、8品脱和5品脱的瓶子,求出不定方程的整数解,按照不定方程的意义则倒酒法为:

      a→b→c→a

       x     y

  倒酒的规则如下:

  (1)按a→b→c→a的顺序;

  (2) b倒空后才能从a中取;

  (3) c装满后才能向a中倒。

  程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>
void 
getti(
int 
a, 
int 
y, 
int 
z);
int 
i;           
//最后需要分出的重量
int 
main()
{
    
int 
a, y, z;
    
printf
(
">>Input Full bottle a,Empty y,z, and Get volumes i:\n"
);
    
//a第一个瓶的容量  y:第二个瓶的容量  z:第三个瓶的容量
    
printf
(
" >> "
);
    
scanf
(
"%d%d%d%d"
, &a, &y, &z, &i);
    
getti(a, y, z);           
//按a -> y -> z -> a的操作步骤
    
printf
(
"\n Press any key to quit..."
);
    
getch();
    
return 
0;
}
void 
getti(
int 
a, 
int 
y, 
int 
z)
//a:第一瓶的容量  y:第二个瓶的容量 z:第三个瓶的容量
{
    
int 
b = 0, c = 0, j = 0;  
// b:第二瓶酒重  c:第三瓶酒重 j: 步数
    
puts
(
" >> The division steps are as follows.\n"
);
    
printf
(
" Bottle:    a<%d> b<%d> c<%d>\n"
,a,y,z);
    
printf
(
"-----------------------------\n"
);
    
printf
(
" Step No.|\n"
);
    
printf
(
"   <%d>   | %4d %4d %4d\n"
,j++,a,b,c);
    
while
(a!=i && b!=i && c!=i )
    
//当三个瓶的酒都!=i
        
if
(!b)
        
{           
//如果第二瓶为空,则从第一瓶倒入第二瓶
            
a -= y;
             
b = y;
        
}
        
else 
if
(c == z)
        
{     
//如果第三瓶满,则将第三瓶倒入第一瓶中
            
a += z;
            
c = 0;
        
}
        
else  
if
(b > z-c)
        
{  
//如果第二瓶的酒>第三瓶的剩余空间
            
b -= (z-c);  
//由第二瓶倒满第三瓶,第二瓶保留剩余部分
            
c = z;
        
}
        
else
        
{          
//将第二瓶全部倒入第三瓶中
            
c += b;
            
b = 0;
        
}
        
printf
(
"   <%d>   | %4d %4d %4d\n"
,j++,a,b,c);
    
}
    
printf
(
"-----------------------------\n"
);
}

本文转自infohacker 51CTO博客,原文链接:http://blog.51cto.com/liucw/1171360

转载地址:http://fgxyl.baihongyu.com/

你可能感兴趣的文章
SSDT Hook的妙用-对抗ring0 inline hook
查看>>
zabbix安装和使用
查看>>
SUSE Login incorrect
查看>>
批量备份脚本
查看>>
安全尽职是企业的阿克琉斯之踵
查看>>
Apache Qpid深入介绍
查看>>
java中获得对象构造器及其构造器参数类型
查看>>
TCP/IP 2.2配置静态路由
查看>>
一个在用的Log日志工具
查看>>
mutt msmtp 邮件发送功能
查看>>
hdfs fsck命令查看HDFS文件对应的文件块信息(Block)和位置信息
查看>>
roger vivier 12 31 One flats Could not offer an excepted
查看>>
saltstack 多master配置
查看>>
我的友情链接
查看>>
双主机hamcp的搭建(贴不了图,附件有详细文档可下载)
查看>>
表格table标签
查看>>
细说路由协议
查看>>
highchart导出图片中文乱码解决
查看>>
oracle 块 区 段
查看>>
函数指针的使用
查看>>