19144 偷懒的士兵3(递归算法)

本文详细讲解了递归在解决士兵巡逻问题中的应用,通过实例说明如何利用递归思想将复杂问题简化,直至达到边界条件。通过n=100和x=47的案例,逐步揭示了如何通过奇偶性调整编号并递归求解,最终判断士兵x是否可能被选中巡逻。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

递归算法是最基础的一种算法,其难点在于初学时很难用递归思想去思考问题。

递归思想:将问题转换成某种数学模型,每一次递归让数学模型的规模变小,直到其到达终结状态。

解题思路:判断编号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,算法的复杂度为mlog_{2}n

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值