递归算法是最基础的一种算法,其难点在于初学时很难用递归思想去思考问题。
递归思想:将问题转换成某种数学模型,每一次递归让数学模型的规模变小,直到其到达终结状态。
解题思路:判断编号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可以被选中。
如查询次数m,算法的复杂度为
#include <iostream>
typedef long long ll;
using namespace std;
int n,x;/**< 检查x能否保留下来,那么每次出队时都要检查x的奇偶性 */
int check(int n,int x)
{
if(n<3)/**< 最后少于3项,说明x一定不会巡逻 */
return 0;
if(n==3)
return 1;
if(x%2)/**< 如果x是奇数项,那么去掉偶数项,剩下元素重新编号,x的新编号是(x+1)/2 */
return check((n+1)/2,(x+1)/2);
else /**< 偶数项同理 */
return check(n/2,x/2);
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
while(cin>>n>>x)
{
if(n==0&&x==0)
break;
cout<<(check(n,x)?"Y\n":"N\n");
}
return 0;
}