题目链接
题目描述
给定四个正整数 。需要将
个任务分配给三位员工(小v、小i、小o),他们能处理的任务上限分别为
。要求计算出所有满足条件的分配方案总数。
一个分配方案指的是一个三元组 ,其中
分别是分配给三位员工的任务数,需要满足以下条件:
解题思路
这是一个简单的组合计数问题。由于所有输入的数值范围都非常小(最大为50),我们可以使用最直观的方法——暴力枚举来解决。
思路是固定其中两位员工的任务数,然后计算出第三位员工需要承担的任务数,最后检查这个分配方案是否满足所有约束条件。
具体算法步骤如下:
- 我们用两层循环来枚举分配给小v(任务数
)和小i(任务数
)的所有可能情况。
- 小v的任务数
可以从
取到他的上限
,同时不能超过总任务数
。所以
的取值范围是
。
- 对于每一个确定的
,小i的任务数
可以从
取到他的上限
,同时也不能超过剩余的任务数
。所以
的取值范围是
。
- 当
和
的值确定后,分配给小o的任务数
也就唯一确定了:
。
- 此时,我们已经通过循环的边界条件保证了
,
以及
且
。唯一还需要检查的条件就是小o的任务数是否超过他的上限,即
。
- 如果
成立,说明我们找到了一个有效的分配方案,就将总方案数加一。
- 遍历完所有可能的
和
的组合后,累计的总方案数就是最终答案。
代码
#include <iostream>
#include <algorithm>
using namespace std;
class Solution {
public:
/**
* 任务分配方案数计算
* @param n int整型 待分配任务总数
* @param x int整型 员工小v能处理的任务数上限
* @param y int整型 员工小i能处理的任务数上限
* @param z int整型 员工小o能处理的任务数上限
* @return int整型
*/
int assignJobs(int n, int x, int y, int z) {
int count = 0;
// 枚举小v的任务数v
for (int v = 0; v <= min(n, x); ++v) {
// 枚举小i的任务数i
for (int i = 0; i <= min(n - v, y); ++i) {
// 计算小o的任务数o
int o = n - v - i;
// 检查小o的任务数是否在其能力范围内
if (o <= z) {
count++;
}
}
}
return count;
}
};
import java.util.*;
public class Solution {
/**
* 任务分配方案数计算
* @param n int整型 待分配任务总数
* @param x int整型 员工小v能处理的任务数上限
* @param y int整型 员工小i能处理的任务数上限
* @param z int整型 员工小o能处理的任务数上限
* @return int整型
*/
public int assignJobs(int n, int x, int y, int z) {
int count = 0;
// 枚举小v的任务数v
for (int v = 0; v <= Math.min(n, x); v++) {
// 枚举小i的任务数i
for (int i = 0; i <= Math.min(n - v, y); i++) {
// 计算小o的任务数o
int o = n - v - i;
// 检查小o的任务数是否在其能力范围内
if (o <= z) {
count++;
}
}
}
return count;
}
}
class Solution:
def assignJobs(self , n: int, x: int, y: int, z: int) -> int:
count = 0
# 枚举小v的任务数v
for v in range(min(n, x) + 1):
# 枚举小i的任务数i
for i in range(min(n - v, y) + 1):
# 计算小o的任务数o
o = n - v - i
# 检查小o的任务数是否在其能力范围内
if o <= z:
count += 1
return count
算法及复杂度
- 算法:暴力枚举
- 时间复杂度:两层循环的复杂度由
和
决定。外层循环最多执行
次,内层循环最多执行
次。因此,总的时间复杂度为
。
- 空间复杂度:算法只使用了常数个额外变量,因此空间复杂度为
。