1.马克思手稿中有一道有趣味数学问题:有30个人,其中有男人、女人和小孩,在一家饭馆吃饭共花了50先令:每个男人花了3先令,每个女人花2先令,每个小孩花了1先令;问男人、女人和小孩各有几人?(穷举法)
2.编写程序求解下式中各字母所代表的数字,不同的字母代表不同的数字(穷举法)
P E A R - A R A P E A 参考答案:
#include
for(p=1;p<=9;p++) for(e=0;e<=9;e++) if(p!=e)
for(a=1;a<=9;a++) if(a!=p&&a!=e)
for(r=0;r<=9;r++)
if(r!=p&&r!=e&&r!=a&&p*1000+e*100+a*10+r-(a*100+r*10+a)==p*100+e*10+a) { printf(\ printf(\ printf(\
printf(\ } }
3.A、B、C、D、E五人在某天夜里合伙捕鱼,到第二天凌辱时都疲惫不堪,于是各自睡觉。日上三竽,A第一个醒来,他将鱼分成5份,把多余的1条鱼扔掉,拿走自己的1份。B第二个醒来,也将鱼分成5份,把多余的1条鱼扔掉,拿走自己的1份,C、D、E依次醒来按同样的方法拿鱼。问他们合伙至少捕了多少条鱼。 参考答案:
#include
{ int n,i,x,flag=1; for(n=6;flag;n++)
{ for(x=n,i=1;flag&&i<=5;i++) if((x-1)%5==0) x=4*(x-1)/5; else
flag=0; if(flag) break; else
flag=1;
}
printf(\}
4.法国著名数学家波瓦松在青年时代研究一个有趣的数学问题:某人有12品脱的啤酒一瓶,想从中倒出6品脱,但没有6品脱的容器,仅有一个8品脱和1个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中倒。 参考答案:
#include
getti(int a,int y,int z) {
int b=0,c=0;
printf(\ while(a!=i||b!=i&&c!=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(\ } }
void main() {
int a,y,z;
printf(\ scanf(\ getti(a,y,z); getti(a,z,y); }
5.黑白子交换:有三个白子和三个黑子如下图布置:
游戏的目的是用最少的步数将上图中白子和黑子的位置进行交换:
游戏规则是:一次只能移动一个棋子;棋子可以向空格中移动,也可以跳过一个对方的棋子进入空格,但不能向后跳,也不能跳过两个棋子,请用计算机实现上述游戏。
算法提示:
① 黑子向左跳过白子落入空格,转⑤ ② 白子向右跳过黑子落入空格,转⑤
③ 黑子向左移动一格落入空格(但不应产生棋子阻塞现象),转⑤ ④ 黑子向左移动一格落入空格(但不应产生棋子阻塞现象),转⑤ ⑤ 判断游戏是否结束,若没有结束,则转①继续。
所谓“阻塞”现象是:在移动棋子的过程中,两个尚未到位的同色棋子连接在一起,使棋盘中的其它棋子无法继续移动。当棋盘上出现“黑、白、空、黑”或“白、空、黑、白”状态时,不能向“左”或向“右”移动中间的棋子,只移动两边的子。
6.魔术师的猜牌术:魔术师利用手中的十三张黑桃,预先将它们排好后迭在一起,牌面朝下。对观众说:我不看牌,只数数就可以猜到每张牌是什么,我大声数数,你们听,不信?你们就看。魔术师将最上面的那张牌数为1,把它翻过来正好是黑挑A,将黑挑A放在桌子上,然后按顺序从上到下数手中的余牌,第二数1、2将第一张牌放在这迭牌的下面,将第二张牌翻过来,正好是黑挑2,也将它放在桌子上。第三次数1、2、3将上面二张牌依次放在这迭牌的下面,再翻第三张牌正好是黑挑3。这样依次进行将13张牌全翻过来,准确无误。问魔术师手中的牌原始次序是怎样按排的。 算法分析:
人工倒推的方法是:在桌子上放十三个空盒子排成一圈,从1开始顺序编号,将黑桃A放入1号盒子中。从下一个空盒子开始对空的盒子计数,当数到第二个空盒子时,将黑桃2放入空盒子中,然后再从下一个空盒子开始对空盒子计数,顺序放入3、4、5?,直到全部放完。注意在计数时跳过非空的盒子,只对空盒子计数,最后牌在盒子中的顺序,就是魔术师手中的牌的顺序。 参考程序:
#include
printf(\ for(i=1;i<=13;i++) {
n=1; do {
if(j>13) j=1; if(a[j]) j++; else
{ if(n==i) a[j]=i; j++; n++; }
}while(n<=i); }
for(i=1;i<=13;i++)
printf(\ printf(\}
7.常胜将军:现有21根火柴,两人轮流取,每人每次可以取1至4根,不可多取,也不能不取,谁取最后一根火柴谁输。现请编写一个程序进行人机对弈,要求人先取,计算机后取;计算机一方为“常胜将军”。
算法分析:在计算机后走的情况下,要想使计算机成为“常胜将军”,必须找出取胜的关键。根据本题的要求可以总结出:后走一方取子的数量与对方刚才一步取子的数量之和等于5,就可以保证一个子是留给先取子的那个人。 参考程序:
#include
printf(\ while(a>0)
{ do
{printf(\ scanf(\
}while(i>4||i<1||i>a); if(a-i>0)
printf(\ if(a=i<=0) {
printf(\ printf(\ break; } else
printf(\ a-=5;
printf(\ } }
8.抢三十:这是中国民间的一个游戏。两人从1开始报数,每人每次可报一个数或两个连续的数,谁先报到30,谁就是胜方。 算法分析:
与第7题相似,但有所不同的是,本题谁先走第一步是可选择的。若计算机走第一步,那么计算机一定是赢家。若人先走第一步,那么计算机只好等待人犯错误,如果人先走第一步且不犯错误,那么人会取胜;否则,计算机会抓住有的一次错误使自己成为胜者。 参考程序:
9.八后问题:在一个8×8的国际旬棋盘上,有八个皇后,每个皇后占一格,要求皇后间不会出现相互“攻击”的现象,既不能有两个皇后处在同一行、同一列或同一对角线上。问有多少种不同的方法。
算法分析:现采用一维数组进行处理。数组的下标i表示棋盘上的么i列,a[i]的值表示皇后在第i列所放的行的位置。如:a[i]=5,表示在棋盘的第一列的第五行放一个皇后。
程序中首先假定a[1]=1,表示第一个皇后放在棋盘的第一列第一行的位置上,然后试探第二列中皇后可能的位置,找到合适的位置后,再处理后续的各列。这样通过反复试探,可以最最终找出皇后的全部位置。 参考程序:
10.乘式还原:有乘法算式如下: O O O × O O O O O O O O O O O O O O O 这18个位置上全部是素数(2、3、5或7),请还原此算式。
算法分析:问题中虽然有18个数位,但只要确定乘数后经过计算就可确定其的数位。乘数和被乘共有5个数位,要求每个数都是质数。完全可以采用穷举法对乘数和被乘数进行穷举,经过
判断后找出答案。但是这种方法给人的感觉是“太笨了”,因为组成的数字只是质数(4个质数),完全没有必要在那么大的范围内进行穷举。只需要试探每一位数字为质数时的情况即可。
程序中并没有直接对质数进行穷举,而是将每个质数与1到4顺序一一对应,在穷举时为处理简单仅对1到4进行穷举处理,待要判断产生的乘积是否满足条件时再利用一个数组完成向对应质数的转换。
参考程序: