17世纪法国数学家加斯帕的一本《数学的游戏问题》描述了许多有趣问题,约瑟问题就是其中之一:
15名基督教徒和15名异教徒同乘一船航行,途中风浪大作,危机万分,领航者告诉大家,只要将全船的一半人投入海中,其余人就能幸免。大家都同意这个办法,并协定者30人围成一圈;由第一个人起报数,每数至第9人便把他投入海中,下一个接着从1开始报数,第9人又被投入海中,依次循环,直至剩下15人为止。问题是如何排法使投入海中的人全为异教徒?
我们现在来用C++来解决这个简单的问题。
用c++模拟当时的情况,我的思路是,30个人全部都是基督教徒,选出15个“叛变”成为异教徒,然后踹他们下海。先用数组将这30个人排列出来(0代表基督教徒,1代表异教徒)
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
考虑到这30个人是围成一个圆形的,所以不建议使用for语句,选择while更简单和便于理解(我在一开始的时候也是用的for语句,在30个人围成圈的情况下我用了另外一个数组来互相替换,将30个人变成60个,虽然最后也实现了,但是代码比用while的长了一倍)
代码如下:
#include<iostream>
using std::cout;
using std::endl;
int main()
{
int num[30]={0};
int m,k,i;
m=0;//m代表选出来的人数
k=0;//k代表循环控制器
i=0;//i用来模拟圆圈
while(m<15)
{
if(num[i]!=1) k++;
if(k==9)
{
num[i]=1;//选出一个异教徒,踢他下水
k=0;//循环控制器初始为0
m++;//记录异教徒人数
}
i++;
if(i==30) i=0;
}
int ship[15],sea[15];//ship代表留在船上的基督教徒,sea代表异教徒
int i2=0,i3=0;
for(int i1=0;i1<30;i1++)
{
if(num[i1]==0)
{
ship[i2]=i1+1;
i2++;
}
else
{
sea[i3]=i1+1;
i3++;
}
}
cout<<"基督教徒应该站在";
for(int i4=0;i4<15;i4++)
{
cout<<ship[i4]<<" ";
}
cout<<"的位置上。";
return 0;
}
按照编程的习惯应该把main定义成viod类型的,但是为了最后展示的效果,用了int。有图有真相
发这个帖子希望和大家交流一下,有更简洁的思路请给我留言。