# 19. 受限任务分配[200分]
# 题目内容
某部门有一批待处理任务,数量为 x;系统按轮次处理任务,每次平分后只保留其中一组进入下一轮,当 x=1 时,处理结束,不再执行任何操作。每一轮按照以下规则处理:
- 当 x 为偶数时,执行一次平分操作:
- 任务数变为 x/2,消耗 1 点成本,操作次数增加 1。
- 当 x 为奇数时,先按如下选择调整任务数为偶数,然后再执行一次平分操作:
- 新增 1 次任务:任务数变为 x+1,消耗 add_cost 点成本,操作次数增加 1;
- 减少 1 次任务:任务数变为 x−1,消耗 return_cost 点成本,操作次数增加 1。
当给定一组 new_tasks,请找出平分任务至 1 时,总成本消耗最少的方案;若达到最低总成本的方案有多种,选择其中操作次数最少的方案。
# 输入描述
new_tasks:当前任务数,1 ≤ new_tasks ≤ 10000budget:成本预算上限,1 ≤ budget ≤ 50add_cost:获取 1 个任务的成本,1 ≤ add_cost ≤ 10return_cost:回收 1 个任务的成本,1 ≤ return_cost ≤ 10
# 输出描述
输出 [最低总成本, 最少操作次数],如果最低总成本超过 budget,输出 [-1,-1];如果输入任务数为 1,直接输出 [0,0]。
# 样例
# 样例 1
输入
5 5 2 1
1
输出
3 3
1
说明:
- 5→4:选择回收任务,成本 1,操作次数 1
- 4→2:平分,成本 1,操作次数 1
- 2→1:平分,成本 1,操作次数 1
总成本为 3,操作次数为 3,未超过预算 5。
# 样例 2
输入
5 2 1 3
1
输出
-1 -1
1
说明:
- 选择获取任务:5→6→3,累计成本为 2,操作次数为 2。此时预算已经用完,但任务数仍为 3,后续任何操作都会超出预算。
- 选择回收任务:仅 5→4 就需要成本 3,已经超过预算。因此无法完成。
# 样例 3
输入
7 30 2 10
1
输出
5 4
1
说明:
- 7→8:选择获取任务,成本 2,操作次数 1
- 8→4:平分,成本 1,操作次数 1
- 4→2:平分,成本 1,操作次数 1
- 2→1:平分,成本 1,操作次数 1
总成本为 5,操作次数为 4。虽然先回收任务也可以使任务数变为偶数,但回收成本较高,不是最低成本方案。
# 代码
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.on('line', (input) => {
const [new_tasks, budget, add_cost, return_cost] = input.split(' ').map(Number);
let ans = [Infinity, Infinity];
const dfs =(task, nums, count) => {
// console.log(task, nums, count);
if (nums > budget || task === 0) {
return;
}
if (task === 1) {
if (nums < ans[0]) {
ans = [nums, count];
} else if (nums === ans[0]) {
ans[1] = ans[1] > count ? count : ans[1];
}
return;
} else {
if (task % 2) {
// 奇数
dfs(task+1, nums+add_cost, count+1);
dfs(task-1, nums+return_cost, count+1);
} else {
dfs(task/2, nums+1, count+1);
}
}
}
dfs(new_tasks, 0, 0);
console.log(ans[0] === Infinity ? '-1 -1' : ans.join(' '));
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34