Description
有N个士兵站成一队列, 现在需要选择几个士兵派去侦察。
为了选择合适的士兵, 多次进行如下操作: 如果队列超过三个士兵, 那么去除掉所有站立位置为奇数的士兵,或者是去除掉所有站立位置为偶数的士兵。直到不超过三个战士,他们将被送去侦察。
现有一个“聪明”的士兵,经常通过选择站在合适的初始位置,成功避免被选中去侦察。
这引起了陈教官的注意。陈教官希望你编写一个程序,
当给定士兵数,以及位置编号,判断站在该位置编号的战士是否可能被抽中巡逻。
注: 按上法得到少于三士兵的情况不用去巡逻。
1 <= N <= 100000
输入格式
有多行(不多于10000行),每行两个数字,第一个数字是士兵人数,第二个数字是位置编号,最后一行是两个0,表示结束
输出格式
对每一行输入,输出一行结果,能被抽中输出Y,不能抽中输出N
最后一行两个0不需要
输入样例
4 1
5 1
0 0
输出样例
N
Y
#include <iostream>
using namespace std;
int n,x;//n是士兵人数,x是位置编号
int check(int n,int x)
{
if(n==3)
return 1; //能被抽中
if(n<3)
return 0; //不能抽中
if(x%2==0) //x位置编号是偶数,则去掉奇数项重新编号
return check(n/2,x/2);
else//x位置编号是奇数,则去掉偶数项重新编号
return check((n+1)/2,(x+1)/2);
}
int main()
{
while(1)
{
cin>>n>>x;
if(n==0&&x==0)
break;
check(n,x);
if(check(n,x)==1)
cout<<"Y"<<endl;
else
cout<<"N"<<endl;
}
return 0;
}
解题思路:判断编号x的士兵是否有可能被选中,那么每次“去除”时一定不能去除这个x,这样当去除到边界条件(人数<=3)时,如果人数恰好等于3,那么能选中x去巡逻,小于3,无论如何无法选中x。
可以尝试用一些具体数据来描述问题,例如n=100,x=47,此时x为奇数项,将偶数项去除,剩余(1,3,5,7......47........99),共50项。这时可以重新编号,编好后共50个士兵,原47号变为(47+1)/2=24号。这样问题就从n=100,x=47,变成了n=50,x=24。按这个思路处理,其递归过程如下:
n x
100 47 去除偶数项
50 24 去除奇数项
25 12
12 6
6 3
3 2 此时剩下3个人,x为2。说明x可以被选中。
————————————————
原文链接:https://blog.csdn.net/sigd/article/details/124830686
参考原文: