持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情
题目描述
Alice 和 Bob 是一场射箭比赛中的对手。比赛规则如下:
Alice 先射 numArrows 支箭,然后 Bob 也射 numArrows 支箭。
分数按下述规则计算:
- 箭靶有若干整数计分区域,范围从 0 到 11 (含 0 和 11)。
- 箭靶上每个区域都对应一个得分 k(范围是 0 到 11),Alice 和 Bob 分别在得分 k 区域射中 ak 和 bk 支箭。如果 ak >= bk ,那么 Alice 得 k 分。如果 ak < bk ,则 Bob 得 k 分
- 如果 ak == bk == 0 ,那么无人得到 k 分。
例如,Alice 和 Bob 都向计分为 11 的区域射 2 支箭,那么 Alice 得 11 分。如果 Alice 向计分为 11 的区域射 0 支箭,但 Bob 向同一个区域射 2 支箭,那么 Bob 得 11 分。
给你整数 numArrows 和一个长度为 12 的整数数组 aliceArrows ,该数组表示 Alice 射中 0 到 11 每个计分区域的箭数量。现在,Bob 想要尽可能 最大化 他所能获得的总分。
返回数组 bobArrows ,该数组表示 Bob 射中 0 到 11 每个 计分区域的箭数量。且 bobArrows 的总和应当等于 numArrows 。
如果存在多种方法都可以使 Bob 获得最大总分,返回其中 任意一种 即可。
示例 1:
输入:numArrows = 9, aliceArrows = [1,1,0,1,0,0,2,1,0,1,2,0] 输出:[0,0,0,0,1,1,0,0,1,2,3,1] 解释:上表显示了比赛得分情况。 Bob 获得总分 4 + 5 + 8 + 9 + 10 + 11 = 47 。 可以证明 Bob 无法获得比 47 更高的分数。
双指针
这个题目我的初步思路是:我是方法是选择回溯法,可以说是万能的标准解法,只需要注意将最后剩余的箭都射入0节点。且每次射箭的最少数量应该等于Alice射箭数量+1。对于Bob而言一个有12个层级,每个层级可以分为得分和不得分。如果想得分,则需要超过Alice一个,若不想得分,则为0即可。所以我们可以枚举每一种情况,并记录下最大值时候的状态。并且从大到小递归每一层级,直到-1停止。若是有多余的箭,则都给层级0。然后用max来记录最大的得分,若是递归到-1的时候,得分大于最大得分,则替换,更新各个层级的状态。递归的时候,分为两种状态,分别为得分/不得分,得分的时候,需要剩余的箭数大于Alice的箭数。具体注意点如下:
- 如果先获得对于bob如果需要得分,对应每个分值所需的最少射箭数量
- 使用堆最少射箭数量的进行回溯
- 我们来维护保存过程中的最大得分
- 如果总射箭数少于numArrows,我们就可以随意分配剩余射箭数。
实现思路如下:
- 先计算每个得分区域的收益(分值/箭的数量)
- 然后按照收益降序排序
- 最后遍历收益数组,如果剩余的箭数量足够一个得分区域,就把它添加到答案里
class Solution {
List<int[]> res = new ArrayList<>();
int[] path = new int[12];
public int[] maximumBobPoints(int n, int[] a) {
backTrace(n, a, 1);
if (res.size() == 0) return new int[12];
int max = 0;
int max_index = 0;
for (int i = 0; i < res.size(); i++) {
int sum = 0;
int[] cur = res.get(i);
for (int j = 0; j < cur.length; j++) {
if (cur[j] > a[j]) {
sum += j;
}
}
if (sum > max) {
max = sum;
max_index = i;
}
}
int[] ans = res.get(max_index);
for (int i : ans) {
n -= i;
}
ans[0] += n;
return ans;
}
public void backTrace(int n, int[] a, int pos) {
if (pos >= a.length || n <= 0) {
res.add(path.clone());
return;
}
for (int i = pos; i < a.length; i++) {
if (n > a[i]) {
n -= a[i] + 1;
path[i] = a[i] + 1;
backTrace(n, a, i + 1);
path[i] = 0;
n += a[i] + 1;
}else {
backTrace(n, a, i + 1);
}
}
}
}
最后
暴力回溯有很多细节要处理好,不然就会一直吃wa。吃的很难受。