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