刚开始听到背包问题时就感觉很熟悉,当老师举出基本的背包问题时就瞬间想起来贪心部分的背包问题,实在没有想明白到底区别在哪。于是我就去搜了一下动态规划这部分的背包问题是否能用贪心的方法解决,答案都是不能,而且都举出了直接明了的例子来证明确实不能,但是都没有具体解释一下为什么不可以或者说这两种背包问题间的区别。所以我又回去看了一下贪心部分的背包问题,仔细琢磨了一下才明白了这其中的不同之处。
  其实,背包问题也就是这类问题的统称,这其中有部分可以用贪心来做有部分不可以,有部分可以用动态规划的方法解出同样也还有别的方法,不过在这里,就只研究动态规划的解法了。
  1.01背包
  正好01背包和贪心算法解决的背包问题最像,所以就在这做一下比较吧。
  
  这个是基础的01背包的描述。
  
  这个是以前用贪心算法求解的背包问题。
  基本一样,除了原始的背包问题多的一句话“物品可以被切开”,这一句话作用可是很关键啊。这一句话的直接作用就是,在所有物品重量总和超过背包的情况下,背包一定能够装满。而对于01背包,在再装入最后一件物品a[n]之前的n-1件物品,选择放入背包的物品可以按照贪心的规则选择,但这最后一件物品的选择就不见得还会遵循某种既定的贪心准则了。这时01背包就不再以某种贪心准则往背包里放东西了,而是用现在动态规划的方法解决。
  基本思路就是以dp[i][j]表示前i件物品放入容量为j的背包中能够得到的最大价值。则对于第i件物品就有两种可能,装与不装,同时对应两种结果。如果不装,dp[i][j]=dp[i-1][j],如果装,则dp[i][j]=dp[i-1][j-a[i]]+v[i],综合来看状态转移方程就是:
  dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[i]]+v[i]);
  不过这还没完。因为在题目求解过程中能够用到的只有i和i-1两行,而前面的数据对于当前状态的求解没有关系,所以可以运用到先前滚动数组的知识去优化。但这还不够,对于当前行来说,对于dp[i][j]状态的求解只需要用到dp[i][1-j]就可以了,所以我们可以在更新数组元素时保证不破坏到需要用到的元素(即左边的元素)而求解当前值,结果就是,dp数组可以压缩成一维而只需要从最右边开始更新数组元素即可。所以j的取值就需要从大到小:
  dp[j]=max(dp[j],dp[j-a[i]]+v[i]);
  要注意的是,虽然数组被降成了一维的,但不能减少计算次数,只是这时这个一维dp数组枚举的元素前后将代表不同的含义(即i与i-1的变化)。不过时间复杂度也应该能够降低,因为数组大小也影响时间复杂度嘛。
  2.完全背包
  
  这是基础的完全背包的描述。
  和01背包区别只是:不再是有n件物品而是有n种物品,每种物品有无限件。则此时dp[i][j]的含义就是前i中物品装入容量为j的背包中能够得到的最大价值。所以,对于第i种物品装多少件才能够得到最大价值就需要讨论一下。因此得到的状态转移方程就是:
  dp[i][j]=max(dp[i-1][j-ka[i]]+kv[i]),(0<=k<=V/a[i]);
  类似01背包的情况,只用到了i和i-1的状态,所以可以做第一步优化(滚动数组),但无论如何,第三重k循环避免不了。具体方法就不再重复了,总之得出来的消去k的状态转移方程就是:
  dp[i][j]=max(dp[i-1][j],dp[i][j-a[i]]*v[i]);
  当得到这一状态转移方程时,再对比01背包的状态转移方程就能够明白,这一方法其实是当放入第i种物品时,如果不装就和i-1种状态相同,而如果装,那么就一件一件的装,在装入某一件时,与装入第i种物品的前一件状态有关。对于装入时来讲,状态j-a[i]就是装入这一件前的状态(所以第一件前就是0件)正好可以实现第i种物品放多少件的状态与第i-1种物品放多少件状态间的衔接,如此就实现了消k。不过还没完,既然在原先k=0处可以实现前i-1状态和第i种之间的衔接,那么衔接之后前i-1种状态的数据就没用了(因为再之后的j变化的状态都是与k=0状态有关),所以状态转移方程可以继续优化:
  dp[j]=max(dp[j],dp[j-a[i]]+v[i]);
  不过,因为这次在第i件物品放入新的一件时状态与第i中物品放入这件之前的状态有关(包括0件),即用到的数据是由i-1到i更新以后的数据,所以枚举j时需要从左往右进行枚举,这就是完全背包与01背包的区别。这样,完全背包的问题就解决了。
  本来打算背包问题就一次性结束的,不过忽然想起来今晚cf还有比赛,所以就把背包问题分成两次吧,而正好也准备整理下cf做的题目,想着专门建立一个专栏挺麻烦的,所以干脆就放这吧。
  B. Nastya and Door
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
On February 14 Denis decided to give Valentine to Nastya and did not come up with anything better than to draw a huge red heart on the door of the length k (k≥3). Nastya was very confused by this present, so she decided to break the door, throwing it on the mountains.

Mountains are described by a sequence of heights a1,a2,…,an in order from left to right (k≤n). It is guaranteed that neighboring heights are not equal to each other (that is, ai≠ai+1 for all i from 1 to n−1).

Peaks of mountains on the segment [l,r] (from l to r) are called indexes i such that l<i<r, ai−1ai+1. It is worth noting that the boundary indexes l and r for the segment are not peaks. For example, if n=8 and a=[3,1,4,1,5,9,2,6], then the segment [1,8] has only two peaks (with indexes 3 and 6), and there are no peaks on the segment [3,6].

To break the door, Nastya throws it to a segment [l,l+k−1] of consecutive mountains of length k (1≤l≤n−k+1). When the door touches the peaks of the mountains, it breaks into two parts, after that these parts will continue to fall in different halves and also break into pieces when touching the peaks of the mountains, and so on. Formally, the number of parts that the door will break into will be equal to p+1, where p is the number of peaks on the segment [l,l+k−1].

Nastya wants to break it into as many pieces as possible. Help her choose such a segment of mountains [l,l+k−1] that the number of peaks on it is maximum. If there are several optimal segments, Nastya wants to find one for which the value l is minimal.

Formally, you need to choose a segment of mountains [l,l+k−1] that has the maximum number of peaks. Among all such segments, you need to find the segment that has the minimum possible value l.

Input
The first line contains an integer t (1≤t≤104) — the number of test cases. Then the descriptions of the test cases follow.

The first line of each test case contains two integers n and k (3≤k≤n≤2⋅105) — the number of mountains and the length of the door.

The second line of the input data set contains n integers a1,a2,…,an (0≤ai≤109, ai≠ai+1) — the heights of mountains.

It is guaranteed that the sum of n over all the test cases will not exceed 2⋅105.

Output
For each test case, output two integers t and l — the maximum number of parts that the door can split into, and the left border of the segment of length k that the door should be reset to.

Example

input
5
8 6
1 2 4 1 2 4 1 2
5 3
3 2 3 2 1
10 4
4 3 4 3 2 3 2 1 0 1
15 7
3 7 4 8 2 3 4 5 21 2 3 4 2 1 3
7 5
1 2 3 4 5 6 1
output
3 2
2 2
2 1
3 1
2 3

  题目很长(cf的好些题目都很长),我也意识到我读题很慢,甚至长一些的题目读起来不知不觉二三十分钟就过去了,这个只能慢慢练了。这个题目大意是:有n座山,其中有几个极大值(peak)山峰,每遇到一个山峰就可以将一块门板一分为二(就是拥有的碎片数+1),求在走过一定数量座山(一定区间内)情况下能够得到最多碎片数,输出碎片数,并输出选取走过山的第一座位置(此区间的左端点),如果有多种情况得到的碎片数最多,输出最小的位置(端点)。
  看到这个题,我的思路就是枚举所有的山,每当遇到一个山峰时存储这个山峰的下标并向前枚举检索在规定区间内能够得到的最大碎片数目并更新碎片数和区间端点值。因为只有遇到更多的碎片数时才会更新碎片数和端点值,所以最终得到的端点值一定是最小的(较大的情况不会去更新)。这个想法很简单,所以wa,代码:

#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<stack>
typedef long long ll;
using namespace std;
int a[200010],p[200010];
int main()
{cin.tie(0);ios::sync_with_stdio(0);int t,n,s,peaks,ans,aans,l;cin>>t;for(int o=1;o<=t;o++){cin>>n>>s;ans=0;for(int i=1,j=1;i<=n;i++){cin>>a[i];if(i>2&&a[i]<a[i-1]&&a[i-2]<a[i-1]){p[j]=i-1;aans=1;for(int k=j;k>=1;k--){if(p[k]<i-s+2) break;else aans++;}if(ans<aans){ans=aans;if(i<=s-1) l=1;else l=i-s+1;  }j++;}if(i==n&&j==1) { ans=1; l=1; }}cout<<ans<<" "<<l<<endl;}
}


  错误的原因是超时,其实在此之前也错了两次,两次选错语言和数组越界就不用说了,但这次改起来就麻烦了。而我想到的解决办法不是每个山峰向前枚举了,而是用数组记录所有的山峰同时再单独记录一个山峰,每当得到一个新的山峰时就判断一下记录的山峰能不能和当前山峰在同一个区间内(注意,一个区间山峰不能在端点处,所以下标的处理上会有些麻烦),如果不在就向后面更新,这样就不用再枚举了。ac代码:

#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<stack>
typedef long long ll;
using namespace std;
int a[200010],p[200010];
int main()
{cin.tie(0);ios::sync_with_stdio(0);int t,n,s,ans,aans,l,tp;cin>>t;for(int o=1;o<=t;o++){cin>>n>>s;ans=0; tp=1;for(int i=1,j=1;i<=n;++i){cin>>a[i];if(i>2&&a[i]<a[i-1]&&a[i-2]<a[i-1]){p[j]=i-1;if(p[j]-p[tp]>s-3) tp++;aans=j-tp+2;if(ans<aans){ans=aans;if(i<=s-1) l=1;else l=i-s+1;  }++j;}if(i==n&&j==1) { ans=1; l=1; }}cout<<ans<<" "<<l<<endl;}
}


  官方的题解我看过了,说实话有点半懂不懂,英文的嘛,不过肯定和我的不一样,而且好像也简单一些。不过我总感觉这种优化时间复杂度的方法虽然不是从老师那学来的但却是从日常学习中得来的,而虽然做题的方法我也没想过用什么算法但其间都有平时算法的影子。

动态规划-背包问题(1)相关推荐

  1. 贪婪算法、递归计算、动态规划背包问题

    //贪婪算法计算背包问题public static double ksack(double[] values, double[] weights, int capacity){double load ...

  2. 动态规划——背包问题(01背包问题)

    动态规划--背包问题(01背包问题) 01背包问题(求最大价值): 问题优化 01背包问题(求方案数): 动态规划--背包问题(01背包问题) 01背包问题(求最大价值): 有N件物品和一个最多能背重 ...

  3. 动态规划背包问题优化空间复杂度——滚动数组

    动态规划背包问题优化空间复杂度--滚动数组 背包问题 空间复杂度优化 Java代码 链接:代码随想录背包问题 背包问题   背包问题是动态规划中基本的问题,我们考虑下面的简单问题:   假设背包容量为 ...

  4. 动态规划——背包问题(详解)

    动态规划是我最早接触的算法,一开始非常简单,固定模板题,后来愈发愈发难起来了,条件,状态压缩等等,难点主要是,状态怎么表示,状态转移方程怎么写,这篇文章将会从背包五大问题详解,希望能帮助到大家去类比, ...

  5. 动态规划——背包问题

    动态规划--背包问题 对于背包问题,今天我们先讲解,01背包,完全背包,和多重背包.我主要从: 什么题可以用背包问题解决 背包问题的模板细节,如何准确写出背包. 1.什么题可以用背包问题解决 看到题目 ...

  6. 动态规划背包问题详解(二)---0-1背包问题

    /**  * 对于技术面试,你还在死记硬背么?  * 快来"播"沙糖橘吧,  * 用视频案例为你实战解读技术难点  * 聚焦Java技术疑难点,实战视频为你答疑解惑  * 越&qu ...

  7. 【入门级】Java解决动态规划背包问题

    目录 前言 动态规划背包问题是什么? 动态规划解题转代码 第一步:拆包填表格 第二步:转为代码 一.首先看空表格:即初始化代码 二.看怎么循环填表格 三.输出结果(最大价值) 第三步:完整代码 动态规 ...

  8. Java-算法-动态规划-背包问题

    看完本篇文章可以再多练习相似题目 算法-动态规划-背包问题-附一 ​​​​​​​ 一. 背包问题介绍 1. 最原始的背包问题 给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择 ...

  9. 动态规划---背包问题分析

    0/1背包 问题描述 有N件物品和一个容量为V的背包,第i件物品的体积为c[i],价值为w[i].求将哪些物品放进背包可以使物品价值总和最大(有两种情况:不要求填满背包和填满背包). 每件商品只有一件 ...

  10. 动态规划 —— 背包问题 P09 —— 背包问题的变化

    [输出方案] 一般而言,背包问题是要求一个最优值,如果要求输出这个最优值的方案,可以参照一般动态规划问题输出方案的方法:记录下每个状态的最优值是由状态转移方程的哪一项推出来的,换句话说,记录下它是由哪 ...

最新文章

  1. boost安装_【环境搭建】源码安装Boost
  2. iOS中定时器NSTimer的开启与关闭
  3. 转载:PHP JSON_ENCODE 不编码中文汉字的方法
  4. Google开源新TensorFlow运行时TFRT,将取代现有进行时
  5. ML:MLOps系列讲解之《MLOps原则之监控/“机器学习成绩”系统/可再现性/松散耦合架构(模块化)/基于ML的软件交付指标/MLOps原则和实践的总结》解读
  6. tensorflow dataset_ops batch()方法 (将此数据集的连续元素合并为批)
  7. powerbuilder中实现多线程同步查询_Power Query中的“追加查询”可以实现合并多个工作表和工作簿...
  8. C# 对象名无效 问题
  9. TensorFlow2快速模型构建及tensorboard初体验
  10. 老男孩mysql参数配置_MySQL启动相关参数解析
  11. Vue实践--v-model实现简易计算器
  12. Dart与系统进程交互
  13. 刨根问底:对于 self = [super init] 的思考
  14. wpf silverlight的Behavior
  15. 使用idea导出数据库脚本
  16. 对 concurrency-made-easy 文章的总结
  17. “法外狂徒”为什么那么多?用程序来告诉你!
  18. 频率f,角频率Ω和数字频率w的物理含义
  19. 各种距离 欧式距离、曼哈顿距离、切比雪夫距离、闵可夫斯基距离、标准欧氏距离、马氏距离、余弦距离、汉明距离、杰拉德距离、相关距离、信息熵...
  20. 基于R语言、MaxEnt模型融合技术的物种分布模拟、参数优化方法、结果分析制图与论文写作

热门文章

  1. 三轮全向底盘:运动学性能分析
  2. document.write
  3. 大数据的应用是什么?有三大关键点
  4. 教学概述+教学内容+教学原则+教学方法+教学组织...+教学模式和教学策略
  5. 如何零基础学习法语,陈家桥法语零基础入门学习
  6. 最近发现有很多人一直在问苹果ID双重认证怎么关闭。
  7. ehvierwer登录与不登录_【虎嗅早报】抖音回应无法用微信账号登录:不清楚是否为人为...
  8. unity 创建自己的像素地图 TileMap
  9. 专访丨互联网安全城市巡回赛冠军肖策:“大满贯”背后的秘密
  10. 美国加州大学河滨分校陈雪梅教授北大招聘Co-PI