每日一题之被疯狂折磨 动态规划 leetcode 5545()

思路 动态规划

一开始用刚学会的回溯算法做,运行超时。改用动态规划,听了yxc的讲解,目前一知半解,好像省了很多步骤。第一次做这种题,先记住模型好思路,以后再战。

题目最后得到的结果是一个类似于一个单调上升函数(是一连串的点,应该不算函数),x轴是年龄,y轴是分数。设分数从小到大,年龄也是从小到大,构成的点是对应x、y轴的球员。

现在先把y轴的分数排列好,这时x轴是无序的。而最终结果一定是上升序列,因此只要任选x轴的点满足Xm >= Xn(m > n,m、n是标号)即可。再在所有的选择中选出最大值即为答案。DFS应该还是超时,思路继续往动态规划上面靠。

闫氏DP分析法:
状态表示:dp[i]:

  1. 集合:包含第i个数的上升序列集合。
  2. 属性:MAX

状态划分:
对dp[i]进行划分。如果要得到包含第i个数的上升序列,可以先划分为两大部分:1.只有第i个数 2. 不只包含第i个数。 再对第二部分进行细化,就是把前面的所有上升序列和i做拼接。前面的上升序列即为包含k的上升序列(0 < k < i),得到
状态转移方程:
dp[i] = scores[i];
dp[i] = max(dp[i], dp[k] + scores[i])(0 < k < i)

为什么必须排序后才能做呢?回到状态转移方程,i与上升子序列拼接是有条件的。如果没有排序,判断条件没法写。动态规划只能得到某一状态的最优解,求不出路径。按照不排序的思路仔细写一下,就会发现i必须要与整个路径进行判断,因为得不到路径判断条件也就无从写起。
排序之后呢?如果i要拼接到包含k的上升序列,只和k判断即可,因为包含k点的路径已经“排序”好了,i如果通过了和k的条件判断,k之前的点的条件判断也能通过。

class Solution {
public:
    static bool comp (const pair<int, int> a, const pair<int, int> b) {
        return a.first < b.first;
    }

    int bestTeamScore(vector<int>& scores, vector<int>& ages) {
        int n = scores.size();

        vector<int> dp(n);
        vector<pair<int, int>> people(n);
        for (int i = 0; i < n; i ++)    people[i] = {scores[i], ages[i]};
        sort(people.begin(), people.end());

        int res = 0;
        for (int i = 0; i < n; i ++) {
            dp[i] = people[i].first;
            for (int j = 0; j < i; j ++) 
                if (people[i].second >= people[j].second)   
                    dp[i] = max(dp[j] + people[i].first, dp[i]);
            if (dp[i] > res)    res = dp[i];
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值