leetcode第109场双周赛 3 - DP,4 - 01背包!
6931. 访问数组中的位置使分数最大
题意
给你一个数组,初始你位于下标 1 处,你可以往后跳到数组任一下标,但不能往前跳。跳到哪个位置,即可获得下标对应的分数,但如果当前下标的数与跳之前下标的数奇偶性不同,那么你会失去分数 x。询问你能获得的最大分数?
思路
一眼动态规划,那么问题在于怎么规划?
我们贪心的考虑,要让分数最大肯定不能简单的选择奇数或者选择偶数,而是选择最大的跳,奇偶不同时仅存在分数 x 的亏损。那么对于每一个位置,我们都希望它是由前面某个位置跳过来,且能让当前位置取得最大值。又因为奇偶性的问题,所以我们可以记两个数 even 和 odd 来保存当前已经处理段结尾为偶数或者结尾为奇数时的最大值。当前数为偶数时更新 even, 当前数为奇数时更新 odd 。最终答案为 \(max(even, odd)\)
可以再理解理解
代码
#define ll long long
class Solution {
public:
long long maxScore(vector<int>& a, int x) {
int n = a.size();
ll even, odd;
even = a[0] + ((a[0] % 2 == 0) ? 0 : -x);
odd = a[0] + ((a[0] % 2 == 0) ? -x : 0);
for(int i = 1; i < n; ++ i){
if(a[i] % 2){
odd = a[i] + max(even - x, odd);
}else{
even = a[i] + max(even, odd - x);
}
}
return max(odd, even);
}
};
6922. 将一个数字表示成幂的和的方案数
题意
就是给你数 n 和数 x,问你有多少种分法,使得 n 表示为互不相同的数的 x 次方的和?结果取余1e9 + 7
比如说:
输入:n = 4, x = 1
输出:2
解释:我们可以将 n 按以下方案表示:
- $n = 4^1 = 4 $
- $n = 3^1 + 1^1 = 4 $
思路
没做出来,看的题解。自己的困惑在于,怎么找几个数的 x 次方和为 n ?总不能暴力匹配吧。。。
题解第一眼 01背包。我:嗯??? 这是 01背包?根本想不到啊!
再一理解,嗷!好像可以!把 n 看作背包容量, \(n_i^x\) 视为物品,那不就是看每个物品一次,能不能装满吗?(必须装满,故初始所有 f 均为 0,除了f[0] = 1)
之后就是朴素的 01背包求法,最终答案为 f[n]
很妙很妙很妙,这一重转换没有看出来!
代码
const int mod = 1e9 + 7;
#define ll long long
class Solution {
public:
int qpow(int a,int x){
int res = 1;
while(x){
if(x & 1) res *= a;
a *=a;
x >>= 1;
}
return res;
}
int numberOfWays(int n, int x) {
vector<ll> f(n + 5, 0);
f[0] = 1;
for(int i = 1; qpow(i, x) <= n ; ++i){
ll v = qpow(i, x);
for(int j = n; j >= v; -- j){
f[j] = (f[j] + f[j - v]) % mod;
}
}
return f[n] % mod;
}
};
本文来自博客园,作者:Qiansui,转载请注明原文链接:https://www.cnblogs.com/Qiansui/p/17576165.html