题目描述
假设你是球队的经理。对于即将到来的锦标赛,你想组合一支总体得分最高的球队。球队的得分是球队中所有球员的分数 总和 。
然而,球队中的矛盾会限制球员的发挥,所以必须选出一支 没有矛盾 的球队。如果一名年龄较小球员的分数 严格大于 一名年龄较大的球员,则存在矛盾。同龄球员之间不会发生矛盾。
给你两个列表 scores 和 ages,其中每组 scores[i] 和 ages[i] 表示第 i 名球员的分数和年龄。请你返回 所有可能的无矛盾球队中得分最高那支的分数 。
示例 1:
输入:scores = [1,3,5,10,15], ages = [1,2,3,4,5]
输出:34
解释:你可以选中所有球员。
示例 2:
输入:scores = [4,5,6,5], ages = [2,1,2,1]
输出:16
解释:最佳的选择是后 3 名球员。注意,你可以选中多个同龄球员。
示例 3:
输入:scores = [1,2,3,5], ages = [8,9,10,1]
输出:6
解释:最佳的选择是前 3 名球员。
提示:
1 <= scores.length, ages.length <= 1000
scores.length == ages.length
1 <= scores[i] <= 106
1 <= ages[i] <= 1000
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/best-team-with-no-conflicts
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
分析
动态规划问题,把问题分割成子问题
球员一共有n位,把球员按照分数由小到大排序,球员下标位0-n-1,问题就变成了
以0号球员为结尾的无矛盾球队中得分最高那支的分数
以1号球员为结尾的无矛盾球队中得分最高那支的分数
以2号球员为结尾的无矛盾球队中得分最高那支的分数
…
以n-1号球员为结尾的无矛盾球队中得分最高那支的分数
以上子问题包含了所有的无矛盾球队中的得分最高分数
在选出最高的即可。
状态:dp[i] 表示以i号球员为结尾的无矛盾球队中得分最高那支的分数
状态转移方程:dp[i]=dp[0~i-1]中满足条件的最大值+score[i]
+score[i]很好理解因为dp[i] 的值一定包含i号球员的分数,因为i表示以i号球员为结尾。
满足条件是指i号球员的年龄不小于该球员前面所有球员的年龄,因为dp[i]本身的计算就满足无矛盾球队这一条件,第i号球员一定在dp[i]选择当中,也就是说dp[i]选择无矛盾球队中的球员年龄一定<=i号球员的年龄,所以比较时只需要比较i号球员的年龄和他前面的一位球员即可
dp[0~i-1]指dp[i]的大小并不是i越大, dp[i]的值越大,我们需要从dp[0]到dp[i-1]中选出符合条件的最大值
以下图为例
代码
class Solution {
public int bestTeamScore(int[] scores, int[] ages) {
int l =scores.length;
int[] dp = new int[l];
int[][] sa = new int[l][2];
for(int i=0;i<l;i++){
sa[i][0]=scores[i];
sa[i][1]=ages[i];
}
Arrays.sort(sa, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
if(o1[0]==o2[0]){
return o1[1]-o2[1];
}
return o1[0]-o2[0];
}
});
// Arrays.sort(sa, (a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);
int res = 0;
for(int m=0;m<l;m++){
for(int n=m-1;n>=0;n--){
if(sa[n][1]<=sa[m][1]){
dp[m]=Math.max(dp[m],dp[n]);
}
}
dp[m]=dp[m]+sa[m][0];
res = Math.max(res,dp[m]);
}
return res;
}
}