File tree Expand file tree Collapse file tree 1 file changed +24
-0
lines changed
Dynamic_Programming/3685.Subsequence-Sum-After-Capping-Elements Expand file tree Collapse file tree 1 file changed +24
-0
lines changed Original file line number Diff line number Diff line change
1
+ ### 3685.Subsequence-Sum-After-Capping-Elements
2
+
3
+ 对于n个元素,问是否可以组合出和为k的方案,就是一个典型的有界背包问题,用o(n* k)的时间复杂度可解。大致算法是:
4
+ ``` cpp
5
+ for (int i=0 ; i<nums.size(); i++) {
6
+ for (int c=k; c>=1; c--) {
7
+ dp[ c] |= dp[ c-nums[ i] ;
8
+ }
9
+ }
10
+ ```
11
+
12
+ 对于此题而言,对于每一个给定的x,我们要用nums里所有小于x的元素,以及剩余的元素当做x使用,问是否能组合出和为k的方案。我们暂时先不考虑第二种用法,即只用nums里小于x的元素。我们发现,随着x的增大,其实第一个for循环里可选的元素种类的上界也在单调增大,故总体这依然是一个o(n* k)可解的问题。
13
+
14
+ 然后更深入地思考,我们将x从小到大遍历的时候,可以不断提升i,从而加入所有不超过x的新nums[ i] ,就可以不断更新dp。同时我们还需要考虑等于x的元素:因为capping的缘故,这样的元素有n-i个。此时我们需要考虑这额外的n-i个元素能否对于组成k有帮助。显然我们可以用同样的背包思想:
15
+ ``` cpp
16
+ for (int j=1 ; j<n-i; j++) {
17
+ if (dp[ k-x* j] ) {
18
+ return true;
19
+ break;
20
+ }
21
+ }
22
+ ```
23
+ 注意,这个过程中我们只是判断是否能组合成k,不会去更新dp。我们始终保持dp[ c] 表示“能否用所有小于x的元素组成c”。这样,即使x变大,dp的定义依然适用。
24
+
You can’t perform that action at this time.
0 commit comments