题目链接
题解
题意
找出若干球员,其分数之和最大且其中不存在年龄较小球员的分数大于年龄较大球员的分数
的情况。
思路
又到了我们最喜欢的动态规划环节了!
- 构建结构体存储分数和年龄,按分数进行排序,将分数大的放在前面或者按年龄进行排序。后续证明排序的必要性;
- 设 d p [ i ] = 以 i 结 尾 且 选 择 i 的 情 况 下 可 获 得 的 最 高 分 数 . dp[i] = 以 i 结尾且选择 i 的情况下可获得的最高分数. dp[i]=以i结尾且选择i的情况下可获得的最高分数.
- 可以得到状态转移方程: d p [ i ] = m a x ( d p [ i ] , s c o r e s [ i ] + d p [ j ] ) dp[i] = max(dp[i], scores[i] + dp[j]) dp[i]=max(dp[i],scores[i]+dp[j])其中 0 ≤ j < i 且 若 a g e s [ i ] < a g e s [ j ] , 则 s c o r e s [ i ] < = s c o r e s [ j ] 0 \leq j < i 且若ages[i] < ages[j],则scores[i] <= scores[j] 0≤j<i且若ages[i]<ages[j],则scores[i]<=scores[j].
这是经过了排序的情况,此时可以推出,若i
和j
满足上述方程,则
i > j
,即若i
的分数小于j
的分数,则i
的年龄小于等于j
的年龄;若i
的分数等于j
的分数,则i
的年龄小于等于j
的年龄。- 我们假设存在
k
和j
满足上述方程,则必然可以推出:j > k
,即若j
的分数小于k
的分数,则j
的年龄小于等于k
的年龄;若j
的分数等于k
的分数,则j
的年龄小于等于k
的年龄。则可以得到i
和k
也满足题目所给的条件:年龄较小的球员分数小于等于年龄较大球员的分数。
如果我们不进行排序,那么就得不到最终i
和k
的关系,因为我们失去了上述的第二个条件。
下文给出了不排序的代码和一个例子。
AC代码
class Solution {
public:
struct Node {
int sco, age;
bool operator<(const Node &a) const {
if (sco == a.sco) return age > a.age;
return sco > a.sco;
}
}e[1010];
int bestTeamScore(vector<int>& scores, vector<int>& ages) {
int size = scores.size();
for (int i = 0; i < size; i++) e[i].sco = scores[i], e[i].age = ages[i];
sort(e, e + size);
vector<int> dp(size, 0);
int maxx = 0;
for (int i = 0; i < size; i++) {
dp[i] = e[i].sco;
int sco = 0;
for (int j = 0; j < i; j++) {
if (e[i].age > e[j].age && e[i].sco < e[j].sco) continue;
sco = max(sco, dp[j]);
}
dp[i] += sco;
maxx = max(maxx, dp[i]);
}
return maxx;
}
};
WA代码
class Solution {
public:
int bestTeamScore(vector<int>& scores, vector<int>& ages) {
int size = scores.size();
vector<int> dp(size, 0);
int ans = 0;
for (int i = 0; i < size; i++) {
dp[i] = scores[i];
int tmp = 0;
for (int j = 0; j < i; j++) {
if ((scores[j] < scores[i] && ages[j] > ages[i]) || (scores[j] > scores[i] && ages[j] < ages[i])) continue;
tmp = max(tmp, dp[j]);
}
dp[i] += tmp;
ans = max(ans, dp[i]);
}
return ans;
}
};
样例
1 3 7 3 2 4
4 5 2 1 1 2