魔术师的猜牌术

魔术师的猜牌术(1)


魔术师利用一副牌中的13张黑桃,预先将它们排好后迭在一起,牌面朝下。对观众说:我不看牌,只数数就可以猜到每张牌是什么,我大声数数,你们听,不信?你们就看。魔术师将最上面的那张牌数为1,把它翻过来正好是黑桃A,将黑桃A放在桌子上,然后按顺序从上到下数手上的余牌,第二次数12,将第一张牌放在这迭牌的下面,将第二张牌翻过来,正好是黑桃2,也将它放在桌子上,第三次数123,将前面两张依次放在这迭牌的下面,再翻第三张牌正好是黑桃3。这样依次进行将13张牌全翻出来,准确无误。问魔术师手中的牌原始顺序是怎样安排的?


*问题分析与算法设计
题目已经将魔术师出牌的过程描述清楚,我们可以利用倒推的方法,很容易地推出原来牌的顺序。
人工倒推的方法是:在桌子上放13空盒子排成一圈,从1开始顺序编号,将黑桃A放入1号盒子中,从下一个空盒子开始对空的盒子计数,当数到第二个空盒子时,将黑桃2放入空盒子中,然后再从下一个空盒子开始对空盒子计数,顺序放入345…,直到放入全部3张牌。注意在计数时要跳过非空的盒子,只对空盒子计数。最后牌在盒子中的顺序,就是魔术师手中原来牌的顺序。
这种人工的方法是行之有效的,计算机可以模拟求解。


#include<stdio.h>
int a[14];
int main()
{
int i,n,j=1; /*j:数组(盒子)下标,初始时为1号元素*/
printf("The original order of cards is:");
for(i=1;i<=13;i++) /*i:要放入盒子中的牌的序号*/
{
    n=1;
	do{
	    if(j>13)
	      {j=1;}/*由于盒子构成一个圈,j超过最后一个元素则指向1号元素*/
	    if(a[j]) 
		  {j++;} /*跳过非空的盒子,不进行计数*/
	    else{ 
		if(n==i) 
		{a[j]=i;} /*若数到第i个空盒子,则将牌放入空盒中*/
	    j++;n++; /*对空盒计数,数组下标指向下一个盒子*/
	   } 
	}while(n<=i); /*控制空盒计数为i*/
}
for(i=1;i<=13;i++) /*输出牌的排列顺序*/
printf("%d ",a[i]);
printf("\n");
}

魔术师的猜牌术(2)


魔术师再次表演,他将红桃和黑桃全部迭在一起,牌面朝下放在手中,对观众说:最上面一张是黑桃A,翻开后放在桌上。以后,从上至下每数两张全依次放在最底下,第三张给观众看,便是黑桃2,放在桌上后再数两张依次放在最底下,第三张给观众看,是黑桃3。如此下去,观众看到放在桌子上牌的顺序是:
黑桃 A 2 3 4 5 6 7 8 9 10 J Q K
红桃 A 2 3 4 5 6 7 8 9 10 J Q K
问魔术师手中牌的原始顺序是什么?


*问题分析与算法设计
本题可在上题的基础上进行编程,不同的在于计数的方法和牌的张数,这些并不影响我们求解题目的思路,仍可按照倒推的方法,得到原来魔术师手中的牌的顺序。


#include<stdio.h>
int a[27];
int main()
{
int i,n,j=1;
a[1]=1; /*初始化第一张牌*/
printf("The original order of cards is:(r:rad b:block):\n");
for(i=2;i<=26;i++)
{
n=1;
do{ 
if(j>26) j=1; /*超过最后一个元素则指向1号元素*/
if(a[j]) j++; /*跳过非空的盒子,不进行计数*/
else{
if(n==3) a[j]=i; /*若数到第3个空盒子,则将牌放入空盒中*/
j++; n++; /*对空盒计数,数组下标指向下一个盒子*/
}
}while(n<=3); /*控制空盒计数为3*/
}
for(i=1;i<=26;i++) /*输出牌的排列顺序*/
{
printf("%c",a[i]>13? 'r':'b');
printf("%d ",a[i]>13? a[i]-13:a[i]);
if(i==13) printf("\n");
}
printf("\n");
}

    原文作者:魔术师发牌问题
    原文地址: https://blog.csdn.net/zpwangshisuifeng/article/details/54693673
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞