算法趣题-Q04

一、问题描述

二、问题分析

        分析题干,很明显是一个将大问题拆分为若干相同的小问题的典型题,那么最简单且有效的方法就是使用递归算法。(说实话,由于太久没有做题,我的第一反应竟然是使用队列进行广度优先遍历。)而递归算法也是一种深度优先遍历。

        下面将给出C/C++的递归算法及广度优先遍历,只给出Python的广度优先遍历。

三、代码实现

1.C/C++实现

#include <iostream>
#include <queue>

using namespace std;

int split_depth(int m, int n, int parts)
{
    // 将 1 根分成 n 根,每次可以进行 m 次切割
    // 最小单位的不能再分割
    if (parts >= n)
    {  
        // 递归出口 
        return 0;
    }
    else if (parts <= m)
    {
        // 当现有段数 count 小于 m,可以同时进行切割
        return 1 + split_depth(m, n, parts * 2);
    }
    else
    {
        // 当现有段数 count 大于 m,且小于 n,只能进行部分切割
        return 1 + split_depth(m, n, parts + m);
    }
}

// 广度优先遍历需要使用队列
int split_breadth(int m, int n)
{
    queue<int> q;
    q.push(n);
    int count = 0;
    while (!q.empty())
    {
        int parts = q.size();
        // 用队列大小 parts 限制切割的顺序
        for (int i = 0; i < m && i < parts; i++)
        {
            int temp = q.front();
            q.pop();
            if (temp >= 4)
            {
                q.push(temp / 2);
                q.push(temp - temp / 2);
            }
            // 不让 1 进入队列
            else if (temp == 3)
            {
                q.push(2);
            }
        }
        count++;
    }
    return count;
}

int main()
{
    cout << split_depth(3, 20, 1) << endl;
    cout << split_depth(5, 100, 1) << endl;
    cout << split_breadth(3, 20) << endl;
    cout << split_breadth(5, 100) << endl;
    return 0;
}

2.Python实现

# coding=utf-8


def split_breadth(m, n):
    count = 0
    parts = [n, ]
    while len(parts) > 0:
        size = len(parts)
        temp = m
        while temp != 0 and size != 0:
            item = parts.pop(0)
            if item >= 4:
                parts.append(item // 2)
                parts.append(item - item // 2)
            elif item == 3:
                parts.append(2)
            temp -= 1
            size -= 1
        count += 1
    return count


if __name__ == '__main__':
    print(split_breadth(3, 20))
    print(split_breadth(5, 100))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值