dp——01背包
今天学习了01背包不算是复习吧,发现完全不会状态之间的转移如此让我捉摸不透尽管很简单但本人觉得还是很难,奇怪地拐点也很难被发现。知道01背包二维的话是很慢的,然后就是非得先打二维毕竟一维是根据二维的想法进行优化的所以决定先啃二维结果漏洞百出,首先呢就是循环顺序了,因为是用前一个被更新过得最优解来更新当前的解所以第二重循环(容量)是可以倒着或者正着来写的。
for(int i=;i<=n;i++)
{
for(int j=m;j>=;j--)
{
f[i][j]=f[i-][j];
if(j>=w[i])
f[i][j]=max(f[i-][j-w[i]]+v[i],f[i][j]);
}
}
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
f[i][j]=f[i-][j];
if(j>=w[i])
f[i][j]=max(f[i-][j-w[i]]+v[i],f[i][j]);
}
}
不管是正着枚举还是倒着枚举都是合法的然后我就发现了f[i][j]有一部分是通过f[i-1][j]枚举过来的所以代码就打成了这样子。
样例为
4 6
2 4
2 6
3 12
2 7
自己手动模拟会对本文的理解更深刻。。。
for(int i=;i<=n;i++)
{
for(int j=w[i];j<=m;j++)
{
f[i][j]=max(f[i-][j-w[i]]+v[i],f[i-][j]);
}
}
但这样子是错误的因为前端的最优值并没有被附上去所以我想很明显我的局部最优解并没有被求出所以导致答案不是最优的,因为01背包靠的是前端的最优解推出末端最优解所以一旦前端的值被w[i]卡掉所以后面的值就不是最优的了,这是我自己打出来的一个错误加深了对01的理解和感触比之前强多了,因为之前总是不明白dp的状态转移之间的规律所以感觉很模糊真正的自己去模拟一遍这个dp的过程会发现很简单。
于是乎我开始了瞎搞因为lyd书上说可以把f数组全部赋值为0xcf,f[0][0]=0,状态即可开始转移然后我就这样打了然后wa了好多慢慢继续打表学长,学长也研究了好大一会才发现它的状态转移是不完全的,差了一个状态f[i][j]=max(f[i][j],f[i][j-1]);于是就这样具体看打表出来的结果。
这个地方明明最优值是19却没有转移过来,发现了问题的所在,如果是一个正解的背包那么f[n][m]里面存的应该是最优解所以出锅了,然后发现最后的值是由10转移而来而这个10在它的那个状态并不是最优解因为在10的前面有一个12,考虑一下10的转移它是因为i-1对应是负无穷所以状态无法转移到当前的值这个地方是很绕的,应该是12的所以最优解就会变化,但是呢在这个地方书上说最优解是在f[n][j]之中书上没毛病所以最好便利一遍找到max即可,看书不认真啊自己。
于是乎洛谷一道01背包由于m过大空间限制O(m*n)直接mle了,所以呢考虑优化空间,书是开了一个滚动数组来节约空间,这个不算很复杂但以后有时间再补充,书上还有一种是01背包的解法将至一维,因为f[i][j]只与f[i-1][j-w[i]]和f[i-1][j]有关所以考虑倒着推就可以使用还没有被更新过得那个f[j]了,这样二维骤降一维。省空间,没有时间换空间哦!
下面是代码:
#include<ctime>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdio>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<cstring>
#include<string>
#include<vector>
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int m,n;
int f[];
int w[],v[];
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();
for(int i=;i<=n;i++)
{
w[i]=read();v[i]=read();
}
for(int i=;i<=n;i++)
{
for(int j=m;j>=w[i];j--)
{
f[j]=max(f[j],f[j-w[i]]+v[i]);
}
}
printf("%d\n",f[m]);
return ;
}
当然01背包这么好的东西可不止这一点,还有一道比较奇怪地01背包。。建议思考如何转移。
原本以为是一道很难的树形dp,结果自己就被骗了,真坑。。
这道题是个01背包,不过形势不太相同我认为。但转移的时候用了点高级的技巧,也算是炫技的一种吧,一行状态转移!
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<ctime>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#define inf 1000000002
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int maxn=;
int n,s;
struct wy
{
int x,y;
}t[maxn];
int f[];
int main()
{
//freopen("1.in","r",stdin);
s=read();n=read();
for(int i=;i<=n;i++)t[i].x=read(),t[i].y=read();
for(int i=;i<=s;i++)f[i]=inf;f[]=;
for(int i=;i<=n;i++)
{
for(int j=s;j>=;j--)
{
if(j>=t[i].x&&f[j-t[i].x]!=inf)f[j]=max(f[j]==inf?:f[j],min(f[j-t[i].x]>?f[j-t[i].x]:inf,t[i].y));
}
}
printf("%d\n",f[s]);
return ;
}
0.0
云水生涯,不是梦,潋滟人生,不成空!
dp——01背包的更多相关文章
- USACO Money Systems Dp 01背包
一道经典的Dp..01背包 定义dp[i] 为需要构造的数字为i 的所有方法数 一开始的时候是这么想的 for(i = 1; i <= N; ++i){ for(j = 1; j <= V ...
- HDOJ(HDU).3466 Dividing coins ( DP 01背包 无后效性的理解)
HDOJ(HDU).3466 Dividing coins ( DP 01背包 无后效性的理解) 题意分析 要先排序,在做01背包,否则不满足无后效性,为什么呢? 等我理解了再补上. 代码总览 #in ...
- POJ.3624 Charm Bracelet(DP 01背包)
POJ.3624 Charm Bracelet(DP 01背包) 题意分析 裸01背包 代码总览 #include <iostream> #include <cstdio> # ...
- HDOJ(HDU).2546 饭卡(DP 01背包)
HDOJ(HDU).2546 饭卡(DP 01背包) 题意分析 首先要对钱数小于5的时候特别处理,直接输出0.若钱数大于5,所有菜按价格排序,背包容量为钱数-5,对除去价格最贵的所有菜做01背包.因为 ...
- HDOJ(HDU).2602 Bone Collector (DP 01背包)
HDOJ(HDU).2602 Bone Collector (DP 01背包) 题意分析 01背包的裸题 #include <iostream> #include <cstdio&g ...
- UVA.10130 SuperSale (DP 01背包)
UVA.10130 SuperSale (DP 01背包) 题意分析 现在有一家人去超市购物.每个人都有所能携带的重量上限.超市中的每个商品有其相应的价值和重量,并且有规定,每人每种商品最多购买一个. ...
- poj 2923 状压dp+01背包
好牛b的思路 题意:一系列物品,用二辆车运送,求运送完所需的最小次数,两辆车必须一起走 解法为状态压缩DP+背包,本题的解题思路是先枚举选择若干个时的状态,总状态量为1<<n,判断这些状态 ...
- DP(01背包) UESTC 1218 Pick The Sticks (15CCPC C)
题目传送门 题意:长度为L的金条,将n根金棍尽可能放上去,要求重心在L上,使得价值最大,最多有两条可以长度折半的放上去. 分析:首先长度可能为奇数,先*2.然后除了两条特殊的金棍就是01背包,所以dp ...
- hihoCoder#1055 : 刷油漆 (树形DP+01背包)
题目大意:给一棵带点权的树,现在要从根节点开始选出m个连通的节点,使总权值最大. 题目分析:定义状态dp(u,m)表示在以u为根的子树从根节点开始选出m个点连通的最大总权值,则dp(u,m)=max( ...
- UVA 562 Dividing coins(dp + 01背包)
Dividing coins It's commonly known that the Dutch have invented copper-wire. Two Dutch men were figh ...
随机推荐
- 《转载》Python并发编程之线程池/进程池--concurrent.futures模块
本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...
- VC利用调试寄存器实现硬件断点源码
[文章标题]:VC利用调试寄存器实现硬件断点源码 [文章作者]:yhswwr(SilenceRet) [作者QQ]:3412259 [编写语言]:C++ [使用工具]:VS2008.VC++9 [本文 ...
- HTML-锚点-JS跳转锚点
window.location.hash使用说明,这篇写的挺详细的 http://www.cnblogs.com/nifengs/p/5104763.html a标签的话是 name,div呢是id, ...
- 正则-input控制输入
大于0的数字:/^(?!0+(?:\.0+)?$)(?:[1-9]\d*|0)(?:\.\d{1,2})?$/ 这正则看不太懂,先放着 作者:Kevin Yang 使用正则表达式找出不包含特定字符串 ...
- Material Design系列第五篇——Working with Drawables
Working with Drawables This lesson teaches you to Tint Drawable Resources Extract Prominent Colors f ...
- 【Web前端开发最佳实践系列】前端代码推荐和建议
一.常用的前端文件的组织结构: 1.js (放置JavaScript代码) lib(放置框架JavaScript文件) custom.js 2.css(放置CSS样式代码) lib(放置框架CSS文件 ...
- vue案例 - vue-awesome-swiper实现h5滑动翻页效果
说到h5的翻页,很定第一时间想到的是swiper.但是我当时想到的却是,vue里边怎么用swiper?! 中国有句古话叫:天塌下来有个高的顶着. 在前端圈里,总有前仆后继的仁人志士相继挥洒着热汗(这里 ...
- H.264 White Paper学习笔记(二)帧内预测
为什么要有帧内预测?因为一般来说,对于一幅图像,相邻的两个像素的亮度和色度值之间经常是比较接近的,也就是颜色是逐渐变化的,不会一下子突变成完全不一样的颜色.而进行视频编码,目的就是利用这个相关性,来进 ...
- tcp连接的状态变迁以及如何调整tcp连接中处于time_wait的时间
一.状态变迁图 二.time_wait状态 针对time_wait和close_wait有个简单的描述帮助理解: Due to the way TCP/IP works, connections ca ...
- MYSQL的索引和常见函数
MySQL的索引 索引机制 MySQL属于关系型数据库,为了提高查询速度,可以创建索引. 索引:由表中的一个或多个字段生成的键组成,这些键存储在数据结构(B树或者hash表中),于是又分为B树索引(I ...