/*题目:
耶稣又15个门徒,其中有一个时出卖耶稣的叛徒,请用排除法找出这位门徒:15人围坐一圈,从第一个开始报号:1,2,3,1,2,3.。。凡是报到“3”的退出圈子,最后留在圈子内的就是叛徒。找出他原来的序号。、
答案:第5个(后面有优化改进方法)
分析:
1、 先说思路,从第一个报数,引入一个计数count,报到3(就是count加到3)的标记位好人,并且让他下次循环不报数。而且count赋值0,继续报数,以此循环。因为报到第十五个人,需要继续从第1个再报数,因此外围还要有个循环,外围第循环用好人数来控制,当好人到15个的时候停止报数,这时最后一个,也就是第十五个好人就是叛徒,因此在标记好人的时候,加上一个pantu的记录,用来记录这个人的序号。最后一次记录的序号就是叛徒。
2、 一开始定义了个二维数组,想的是一个定义序号,一个定义是否是好人(0,1),后来想了想没必要,序列号直接下标就可以了。
*/
#import
int main()
{
int people[15] = {0}; // 定义数组15个人,下标+1就代表序号。元素0代表不知道是否是好人。当后面改为1的代表是好人。
int count = 0; // 用来记报的数,循环时从1开始,数到3就归0.
int haoren = 0; // 好人个数,报到3,好人就加一个
int pantu = 0; // 叛徒,最后一个好人就是叛徒
for (; haoren <= 14;) // 外循环,直到出现15个好人时停止循环
{
for (int i = 0; i <= 14; i++) // 15个人从头报数
{
if (people[i] == 0) // 如果不确定是好人,就报数
{
count ++; // 只要有人报数就+1
if (count == 3) // 报到3时,进行下面到操作
{
count = 0; // 报到计数归0,后面到人继续从1报
people[i] = 1; // 报3的人标记为好人,后面不再参与报数
haoren ++; // 好人数加1
pantu = i+1; // 叛徒暂时标记为最后这个报数的人(一开始没有+1,忘了下标是从0开始的)
}
}
}
}
printf("叛徒的序号是%d\n",pantu); // 打印出叛徒的序号,打印结果为5
return 0;
}
/*
我把代码又改进了一下,双循环改为一个循环。(建议先浏览第十题后再浏览本页代码)
*/
#import
int main()
{
int people[15] = {0};
int count = 0;
int haoren = 0;
int pantu = 0;
int i = 0; // 这一句要写到外面了。不能每次循环都从0开始。
for (; haoren <= 14;i ++ ) // 从此处改动,循环一直继续,直到出现第十五个好人结束。
{
if (people[i] == 0)
{
count ++;
if (count == 3)
{
count = 0;
people[i] = 1;
haoren ++;
pantu = i+1;
}
}
if (i == 14) // 报数到第十五个人,返回头再开始报数
{
i = -1;
}
}
printf("叛徒的序号是%d\n",pantu);
return 0;
}