C语言编程100题-6.4

6.4
某部队进行新兵队列训练,将新兵从1开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始1至2报数,凡报到2的出列,剩下的向小序号方向靠拢,再从头开始进行1至3报数,凡报到3的出列,剩下的向小序号方向靠拢,继续从头开始进行1至2报数,以后从头开始轮流进行1至2报数、1至3报数直到剩下的人数不超过三人为止。编写程序,输入数N为最开始的新兵人数(20 < N < 6000),输出剩下的新兵最初的编号。

#include<stdio.h>//bug容易泛滥的一道题目,for循环体很需要严谨的数学思维:如何转换,何时停止循环
int main()
{
	int n,i,a[6000];
	scanf("%d", &n);
	for (i = 0; i < n; i++)
		a[i] = i + 1;//定义队列数
	while (n > 3)
	{
		for (i = 0; 2 * i < n; i++)
			a[i] = a[2 * i];
		n = i;//报号为2的出列
		while (n > 3)//n<=3时停止循环
		{
			if ((n + 2) % 3 != 0)/*case1:报号为3者出列后,末尾有单独两项或无项;
				例如输入n=9,报号为2的出列得到1 3 5 7 9,报号为3的出列(去除5),5后面有单独两项7和9
				例如输入n=11,报号为2的出列得到1 3 5 7 9 11,报号为3的出列(去除5 11),11后面无项*/
			{
				for (i = 0; ((3 * i) / 2 + 1) < n; i = i + 2)
					a[i] = a[(3 * i) / 2], a[i + 1] = a[(3 * i) / 2 + 1];
				n = i;
			}
			else/*case2:报号为3者出列后,末尾只有单独一项;
								 例如输入n=7,报号为2的出列得到1 3 5 7,报号为3的出列(去除5),5后面只有单独一项7*/
			{
				for (i = 0; ((3 * i) / 2 + 1) < n; i = i + 2)
					a[i] = a[(3 * i) / 2], a[i + 1] = a[(3 * i) / 2 + 1];
				a[i] = a[(3 * i) / 2];
				n = i+1;
			}
			break;//易遗漏这个break
		}
	}
	for (i = 0; i < n; i++)//输出最后的队列
	{
		printf("%d", a[i]);
		if (i != n - 1)
			printf(" ");//空格输出控制
	}
		system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/nollysoul/article/details/90208018