动态规划
花无凋零之时
这个作者很懒,什么都没留下…
展开
-
【牛客网】KY139 毕业bg
关于贪心的使用————每个阶段的最优状态都是由上一个阶段的最优状态得到的那么该问题的状态和阶段是什么呢?现在来看关于阶段的定义,所谓阶段是指随着问题的解决,在同一个时刻可能会得到的不同状态的集合。我们可以把时间作为划分阶段的尺度,那么就是第i小时,就是第i阶段。因为本题要求最大快乐度,那么状态的对象一定是最大快乐度,既然阶段是时间,那么怎么定义才能让一个阶段包含多个不同状态的集合,那就是参加的不同活动的集合所带来的最大快乐度,对于本题,在一个给定的时间i可能一个人参加了活动1,但他同样能通过.原创 2022-03-02 17:36:56 · 238 阅读 · 0 评论 -
【AcWing】4. 多重背包问题 I
多重背包问题,需要对数据进行分解,将其转换为0-1背包问题:#include <iostream>#include <cstdio>using namespace std;const int N = 1000 + 10;int w[N], v[N], k[N], weight[N], value[N], dp[N];int main(){ int n, m; while(scanf("%d%d", &n, &m) != EOF){.原创 2022-03-02 08:40:52 · 216 阅读 · 0 评论 -
【牛客网】DP31 【模板】完全背包
第一行的输出就是典型的完全背包问题,而第二行则是要求体积固定价值最大,因此需要先将dp2初始化为int类型所能表达的最小值,并将dp2[ 0 ]赋值为0。#include<iostream>#include<cstdio>#include<climits>using namespace std;const int N = 1000 + 10;int v[N], w[N], dp1[N], dp2[N];int main(){ int n, .原创 2022-03-01 15:55:13 · 157 阅读 · 0 评论 -
【牛客网】DP30 【模板】01背包
第一行的输出就是典型的0-1背包问题,而第二行则是要求体积固定价值最大,因此需要先将dp2初始化为int类型所能表达的最小值,并将dp2[ 0 ]赋值为0。#include<iostream>#include<cstdio>#include<climits>using namespace std;const int N = 1000 + 10;int w[N], v[N], dp1[N], dp2[N];int main(){ int n,.原创 2022-03-01 15:37:44 · 112 阅读 · 0 评论 -
【牛客网】KY41 放苹果
利用动态规划求解。当m >= n时,要么每个盘子至少有一个苹果,要么至少有一个空盘子,所以dp[ i ][ j ] = dp[ i ][ j - 1 ] + dp[ i - j ][ j ]。当m < n时,则至少有n - m个盘子空着,即最多有m个盘子有苹果,所以dp[ i ][ j ] = dp[ i ][ i ]。边界条件,当只有一个盘子或者没有苹果的时候,只有一种放法。#include<iostream>#include<cstdio>using .原创 2022-03-01 15:18:49 · 529 阅读 · 0 评论 -
【POJ】1163 The Triangle
这道题需要利用动态规划来求解,可以先利用matrix[][]存储三角形,然后dp[ i ][ j ]代表从( i , j )点出发到达底部路径之和的最大值,则dp[ 0 ][ 0 ]即为问题的解。对应的状态转换方程为:dp[ i ][ j ] = max(dp[ i + 1 ][ j ], dp[ i + 1 ][ j + 1 ]) + matrix[ i ][ j ]#include <iostream>#include <cstdio>#include <cs.原创 2022-03-01 14:25:16 · 483 阅读 · 0 评论 -
动态规划中的背包问题总结
背包问题是动态规划中的一种经典题型, 背包问题的变体繁多且复杂,这里总结一下背包问题中的0-1背包、完全背包以及多重背包三类问题。0-1背包问题描述:有n件物品,每件物品的重量为w[ i ],价值为v[ i ],现在有容量为m的背包,问如何选择物品使得装入背包的物品价值总量最大。对于这种问题,我们首先想到的就是遍历所有的情况,然后找到其中价值总量最大的,但是这个方法的时间复杂度为O(2n),复杂度太高了,因此需要用动态规划来求解该类问题,则可以使得时间复杂度降为O(nm)。首先设置一个二维数组dp[原创 2022-03-01 13:41:59 · 1156 阅读 · 0 评论 -
【POJ】1384 Piggy-Bank
这是完全背包问题求最小值,其状态转移方程为:dp[ j ] = min(dp[ j ], dp[ j - w[ i ] ] + v[ i ])#include <iostream>#include <cstdio>#include <climits>using namespace std;const int N = 1e4 + 10;int main(){ int t, e, f, n, v[N], w[N], dp[N]; sc.原创 2022-03-01 10:49:28 · 243 阅读 · 0 评论 -
【牛客网】KY14 最小邮票数
这是0-1背包问题的变形,0-1背包问题求最大值,这个求最小值,同时每件物品的价值都是1,其状态转移方程为:dp[ j ] = min(dp[ j ], dp[ j - w[ i ] ] + 1)#include<iostream>#include<cstdio>using namespace std;const int N = 100 + 10;int main(){ int m, n, w[N], dp[N]; while(scanf("%.原创 2022-03-01 10:19:49 · 160 阅读 · 0 评论 -
【牛客网】KY75 采药
典型的0-1背包问题,其状态转移方程为:dp[ j ] = max(dp[ j ], dp[ j - weight [ i ] ] + value [ i ])#include<iostream>#include<cstdio>using namespace std;const int N = 1000 + 10;int main(){ int t, m, weight[N], value[N], dp[N]; while(scanf("%d%.原创 2022-03-01 10:08:02 · 219 阅读 · 0 评论 -
【牛客网】KY114 Coincidence
最长公共子序列问题:#include<iostream>#include<cstdio>#include<string>using namespace std;const int N = 100 + 10;int dp[N][N];int main(){ string str1, str2; while(cin>>str1>>str2){ str1 = " " + str1; .原创 2022-02-28 21:28:18 · 90 阅读 · 0 评论 -
【牛客网】KY73 合唱队形
思路:除第一个和最后一个以外,以每个数为中间数。求此数的左边最大升序子序列的长度dp1[ i ],以及右边最长降序子序列的长度dp2[ i ],最少出列数应为min( n - dp1[ i ] - dp2[ i ] + 1)的值#include<iostream>#include<cstdio>#include<climits>using namespace std;const int N = 100 + 10;int main(){ int .原创 2022-02-28 21:06:05 · 196 阅读 · 0 评论 -
【牛客网】KY78 最大上升子序列和
对应的状态转移方程为:dp[ i ] = max (arr[ i ], dp[ j ] + arr[ i ] | j < i && arr[ j ] < arr[ i ])#include<iostream>#include<cstdio>using namespace std;const int N = 1000 + 10;int main(){ int n, arr[N], dp[N]; while(scanf(.原创 2022-02-28 20:45:18 · 186 阅读 · 0 评论 -
【牛客网】KY77 拦截导弹
求最长不增子序列与求最长递增子序列类似,只是状态转移方程有区别:dp[ i ] = max (1, dp[ j ] + 1 | j < i && arr[ j ] >= arr[ i ])#include<iostream>#include<cstdio>using namespace std;const int N = 30;int main(){ int n, arr[N], dp[N]; while(scanf.原创 2022-02-28 19:15:31 · 254 阅读 · 0 评论 -
【牛客网】KY141 最大连续子序列
利用的是求连续最大子序列和的办法:(1)当前面最大子序列和为负数的时候,后面的加上其一定会比后面本身更小,所以把sum置为0,重新寻找连续最大子序列和(2)重新寻找的时候,也就是新序列开始的时候,记录下此时的数,可能是最大连续子序列和的开始数(3)当新的连续最大子序列和大于之前的,说明之前的子序列不是所求,则更新序列的开始数和结尾数#include<iostream>#include<cstdio>#include<climits>using names.原创 2022-02-28 18:45:49 · 122 阅读 · 0 评论 -
【牛客网】KY63 最大子矩阵
要求一个二维矩阵的最大子矩阵,首先要会求一维矩阵的最大子矩阵(即一维数组连续最大和)假设原二维矩阵的最大子矩阵所在的行为i到j当 i = j 时,则最大子矩阵为第 i 行的连续最大和当 i != j 时,现在我们已经知道最大子矩阵的行,要求的是其所在的列我们把从第 i 行到第 j 行的所有行相加,得到一个只有一行的一维数组,则该一维数组的连续最大和就是最大子矩阵。这里有个小技巧是,可以先利用一个temp二维数组存储matrix每一行累加的结果,然后只需要执行temp[ j ] [ k ] -.原创 2022-02-28 13:05:32 · 308 阅读 · 0 评论 -
【牛客网】KY8 整数拆分
思路一:记f(n)为n的划分数,我们有递推公式:f(2m + 1) = f(2m),f(2m) = f(2m - 1) + f(m),初始条件:f(1) = 1。证明:证明的要点是考虑划分中是否有1。记:A(n) = n的所有划分组成的集合,B(n) = n的所有含有1的划分组成的集合,C(n) = n的所有不含1的划分组成的集合,则有: A(n) = B(n)∪C(n)。又记:f(n) = A(n)中元素的个数,g(n) = B(n)中元素的个数,h(n) = C(n)中.原创 2022-02-27 15:50:37 · 774 阅读 · 0 评论 -
【牛客网】JZ42 连续子数组的最大和
每次固定一个元素为末尾元素,然后找该元素之前构成的子序列的最大值,arr[ i ] 用于存储以array[i]为末尾元素的子数组的和的最大值,子数组的元素的相对位置不变,maximum用于存储子数组和的最大值:class Solution {public: int FindGreatestSumOfSubArray(vector<int> array) { const int N = 2e5 + 10; int arr[N] = {0}; .原创 2022-02-23 10:36:37 · 479 阅读 · 0 评论 -
【牛客网】JZ47 礼物的最大价值
代码:class Solution {public: int maxValue(vector<vector<int> >& grid) { int m = grid.size(); int n = grid[0].size(); const int N = 200 + 10; int dp[N][N]; for(int i = 0; i <= m; i++) dp[i][0] .原创 2022-02-20 19:44:45 · 404 阅读 · 0 评论 -
【牛客网】KY66 点菜问题
典型的0-1背包问题,将价格视作重量,将评价分数视作价值即可:#include<iostream>#include<cstdio>using namespace std;const int N = 1000 + 10;int weight[N], value[N];int dp[N][N];int main(){ int n, m; while(scanf("%d%d", &n, &m) != EOF){ for.原创 2022-02-08 23:02:14 · 368 阅读 · 0 评论 -
【POJ】1458 Common Subsequence
最长公共子序列问题是动态规划的经典问题之一,对于长度分别为n和m的两个序列,若是最后一个元素是一样的,那么我们只需要看长度分别为n-1和m-1的两个序列,若是不一样,则需要比较长度分别为n-1和m的两个序列或者长度分别为n和m-1的两个序列哪个的公共子序列是最长的。递归解法:#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N = 100.原创 2022-02-08 21:44:34 · 145 阅读 · 0 评论 -
【POJ】2533 Longest Ordered Subsequence
求最长递增子序列是动态规划的经典问题之一,其思想与求最大子序列之和类似,区别就在于前者还需要判断前面的元素与当前元素的大小关系。首先是使用递归的方法:#include <iostream>#include <cstdio>using namespace std;const int N = 1000 + 10;int arr[N], dp[N];int Func(int n){ if(dp[n] != -1) return dp[n]; if(n.原创 2022-02-08 20:40:18 · 335 阅读 · 0 评论 -
【牛客网】KY22 最大序列和
求最大子序列和是动态规划的经典问题之一,其思想就是首先固定尾元素arr[i],然后就是判断arr[i],arr[i]及其前面元素构成的子序列的大小,若把当前元素设为F(i),则问题可以抽象为F(i)=max(arr[i], F(i-1) + arr[i]),因为要找 i 与其前面元素之和的最大值,则必定会有 i-1 ,进而导致问题规模缩小。首先用递推的方式求:#include<iostream>#include<climits>using namespace std;.原创 2022-02-08 16:26:51 · 356 阅读 · 0 评论 -
【牛客网】KY225 N阶楼梯上楼问题
这道题仔细一想,其实就是类似斐波那契数那种,因为一次只能走一阶或者两阶,所以当为0阶楼梯时,则有0种上楼方式,1阶楼梯则有1种上楼方式,但是2阶楼梯则有2种上楼方式,而当有n(n>2)阶楼梯时,想要上去则只能是从n-1阶或者n-2阶楼梯才能上去,因此可以得到F(n)=F(n-1)+F(n-2),但是因为F(2)=2,所以与斐波那契有一点区别:#include<iostream>using namespace std;const int N = 91;long long me.原创 2022-02-08 15:30:34 · 235 阅读 · 0 评论