本文主要是介绍leetcode_1402 做菜顺序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1. 题意
给定一个数组sa
,你可以任意选取其中的元素进行排列。
求舒适值得最大值。
舒适值定义为 a n s = ∑ i = 0 k ( i + 1 ) ∗ s a i ans = \sum_{i = 0}^{k}(i + 1) *sa_i ans=∑i=0k(i+1)∗sai
做菜顺序
2. 题解
2.1 贪心 + 前缀和
我们在sa
中选取元素时,需要进行排序。
为了使得ans
的值最大,我们需要将较大的 s a i sa_i sai值与较大的 i i i相乘。
若 ∀ s a i ≥ 0 , 0 ≤ i ≤ s a . s i z e ( ) \forall sa_i \ge 0,0 \le i \le sa.size() ∀sai≥0,0≤i≤sa.size()
则我们直接选取所有元素即可,但是 s a sa sa中存在负数。
我们需要比较添加一个负数带来的收益是否为正。
我们可以从大到小进行排序得到序列 a a a,这样会很方便进行计算,每次添加一个新元素 a k a_k ak对原有序列增
加的收益为
i n c = s u m i = 0 k a i inc = sum_{i =0}^{k } a_i inc=sumi=0kai
即前缀和
P r e f i x S u m ( a , k + 1 ) PrefixSum(a, k + 1) PrefixSum(a,k+1)
当 i n c > 0 inc > 0 inc>0时,我们继续添加元素。
当 i n c < = 0 inc <= 0 inc<=0时,退出。
- 代码
class Solution {
public:int maxSatisfaction(vector<int>& satisfaction) {sort(satisfaction.rbegin(), satisfaction.rend());int sz = satisfaction.size();int res = 0;int prefix = 0;for ( int i = 0; i < sz; ++i) {if (prefix + satisfaction[i] > 0) {res += prefix + satisfaction[i];prefix += satisfaction[i];}else break;}return res;}
};
2.2 动态规划
排序一下,每道菜都可以选择做或者不做,变成了一个0-1背包的问题。
用dp[i][j]
表示前i
个菜,选择j
道菜的最大收益。
d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − 1 ] + i ∗ s a t i f i c a t i o n [ j ] ) dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]+i*satification[j]) dp[i][j]=max(dp[i−1][j],dp[i−1][j−1]+i∗satification[j])
需要排序的解释直接看官解了
class Solution {
public:int maxSatisfaction(vector<int>& satisfaction) {sort(satisfaction.begin(), satisfaction.end());int sz = satisfaction.size();vector<vector<int>> dp(sz + 1, vector<int>(sz + 1));int res;for ( int i = 1; i <= sz; ++i) {for (int j = 1; j <= i; ++j) {dp[i][j] = dp[i - 1][j - 1] + satisfaction[i - 1] * j;if ( j < i)dp[i][j] = max(dp[i - 1][j], dp[i][j]);res = max(res, dp[i][j]);}}return res;}
};
这篇关于leetcode_1402 做菜顺序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!