「Day 9 & 10—DP问题」
DP问题
定义
什么是
在我看来就是一种递推的
DP板子问题
P1115 最大子段和
思路
我们用
代码
点击查看代码
#include<iostream>
using namespace std;
const int MAXN = 2 * 1e6 + 5;
int a[MAXN];
int dp[MAXN];
int n,ans = -10086;
int main(){
cin >> n;
for(int i = 1;i <= n;i ++) cin >> a[i];
for(int i = 1;i <= n;i ++){
if(dp[i - 1] >= 0) dp[i] = dp[i - 1] + a[i];
else{
dp[i] = a[i];
}
ans = max(dp[i],ans);
}
cout << ans << "\n";
return 0;
}
最大子矩阵问题
思路
首先呢这个题没有找到有这个题的
最大子矩阵这个问题太大了,如果是枚举的话
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
//j表示第j列,剩下的那一维和正常的前缀和没什么大区别。
pre[i][j] = pre[i - 1][j] + a[i][j];
}
}
接下来如何求呢,我们既然知道了在第
3 3
1 -2 3
-4 5 -6
7 -8 9
对于每一列的前缀和为
1 -2 3
-3 3 -3
4 -5 6
例如我们要算上界为
3 -3 3
这个该如何算呢?
利用
计算后再用最大子段和进行计算即可。
// 求解最大子矩阵和
long long ans = -inf;
for (int i = 1; i <= n; i++) { // 枚举上边界
for (int j = i; j <= n; j++) { // 枚举下边界
long long sum = 0;
// 第 k 列,[i,j] 的和为:pre[j][k] - pre[i - 1][k]
// 所以就转换为最大子段和问题了
for (int k = 1; k <= m; k++) {
long long tmp = pre[j][k] - pre[i - 1][k];
if (sum >= 0) {
sum += tmp;
} else {
sum = tmp;
}
ans = max(ans, sum);
}
}
}
B3637 最长上升子序列
思路+代码
#include<iostream>
using namespace std;
int n;
int a[10005],dp[10005];
int main(){
cin >> n;
for(int i = 1;i <= n;i ++){
cin >> a[i];
}
for(int i = 1;i <= n;i ++){
dp[i] = 1;
for(int j = 1;j < i;j ++){
//保证上升
//如果是最长不下降子序列就把<改为<=即可
if(a[j] < a[i]){
//取最大的
dp[i] = max(dp[i],dp[j] + 1);
}
}
}
int ans = -1;
for(int i = 1;i <= n;i ++){
ans = max(ans,dp[i]);
}
cout << ans << "\n";
return 0;
}
P1439 【模板】最长公共子序列
思路
首先是我们考虑状态,
代码(无优化50pts)
点击查看代码
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int a[200005],b[200005];
int dp[8005][8005];
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
cin>>b[i];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
//两种情况
if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1] + 1;
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
cout<<dp[n][n]<<endl;
return 0;
}
简单背包问题
P1048 [NOIP2005 普及组] 采药
思路
这个题可以说是最正规的
对于第
代码
点击查看代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[21][1010];
int w[21], c[21];
int main() {
int N, V;
cin >> N >> V;
for (int i = 1; i <= N; i++) {
cin >> w[i] >> c[i];
}
for (int i = 1; i <= N; i++) {
for (int j = 0; j <= V; j++) {
if (j >= c[i]) {
dp[i][j]=max(dp[i-1][j-c[i]]+w[i],dp[i-1][j]);
} else {
dp[i][j]=dp[i-1][j];
}
}
}
cout << dp[N][V] << endl;
return 0;
}
P1757 通天之分组背包
思路
这个题和上个题唯一不同是这个题每个物品有好多件,于是我们就可以在转移的过程中枚举件数
代码
点击查看代码
for (int i = 1; i <= N; i++) {
for (int j = 0; j <= V; j++) {
for (int k = 0; k <= n[i]; k++) {
if (j >= c[i] * k) {
dp[i][j] = max(dp[i - 1][j - c[i] * k] + w[i] * k, dp[i][j]);
}
}
}
}
P1616 疯狂的采药
思路
这个题和上一个的唯一区别是这个题我物品你可以随便取,那么又该如何去做呢?
朴素的方法是这样:
for (int i = 1; i <= N; i++) {
for (int j = 0; j <= V; j++) {
for (int k = 0; k * c[i] <= j; k++) {
dp[i][j] = max(dp[i - 1][j - c[i] * k] + w[i] * k, dp[i][j]);
}
}
}
但是啊这破玩意时间复杂度太高了啊,那就优化,如何优化嘞?我们发现
然鹅
所以
代码
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= v; j++) {
if (j >= c[i]) {
dp[i][j] = max(dp[i][j - c[i]] + w[i], dp[i - 1][j]);
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
简单DP问题
Frog 1
思路
这个题明显是一个构造题,首先构造
代码
点击查看代码
#include<iostream>
#include<cmath>
using namespace std;
const int MAXN = 1e5 + 5;
int dp[MAXN];
int h[MAXN];
int n;
int main(){
cin >> n;
for(int i = 1;i <= n;i ++){
cin >> h[i];
}
dp[1] = 0;
dp[2] = abs(h[2] - h[1]);
for(int i = 3;i <= n;i ++){
dp[i] = min(dp[i - 1] + abs(h[i] - h[i - 1]),dp[i - 2] + abs(h[i] - h[i - 2]));
}
cout << dp[n] << "\n";
return 0;
}
点击查看代码
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
const int MAXN = 1e5 + 5;
int dp[MAXN];
int h[MAXN];
int n,k;
int main(){
memset(dp,0x3f3f3f3f,sizeof(dp));
cin >> n >> k;
for(int i = 1;i <= n;i ++){
cin >> h[i];
}
dp[1] = 0;
dp[2] = abs(h[2] - h[1]);
for(int i = 3;i <= n;i ++){
for(int j = max(1,i - k);j <= i;j ++){
dp[i] = min(dp[i],dp[j] + abs(h[i] - h[j]));
}
}
cout << dp[n] << "\n";
return 0;
}
本文来自一名初中牲,作者:To_Carpe_Diem
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战