背包的自我修养

大概了解了背包九讲前面四章的内容。先 ORZ DD大神一分钟……59,58,57……

……3,2,1。好,结束,总结一下三种背包问题,01,完全,多重。都隶属于动态规划问题。

下面这是个人四天来的学习体会。

区别方式也很简单:

①物品数量只有一个,只存在放和不放的区别,01背包。

②物品数量有无限多个,或者能完全把背包装满,完全背包。

③物品数量有限而且不能把背包装满。多重背包。

这也是在选择策略时的调用条件。

我们这样来表示:

int n,m;
//物品种类 和 背包容量
int dp[10001];
//背包不同状态的价值
int cost[1001],value[1001],cot[1001];
//费用,价值,数量

当 cot[i]==1的时候,只存在放或者不放,这时候就选择01背包策略。

if(cot[i]==1)
                zeroonepack(cost[i],value[i]);

当cost[i]*cot[i]>=m的时候,表明比能装满包还多,就用完全背包策略。

else if(cot[i]*cost[i]>=m)
                completepack(cost[i],value[i]);

剩下情况就使用 多重背包策略。

else
                multiplepack(cost[i],value[i],cot[i]);

这几种策略,我前面的解题报告提过,现在都写出来。

01背包的情况:

void zeroonepack(int cost,int value)
{
    for(int i=m;i>=cost;i--)
        dp[i]=max(dp[i],dp[i-cost]+value);
}
//01背包

从 m->0 保证是由上一状态得来。

完全背包:

void completepack(int cost,int value)
{
    for(int i=cost;i<=m;i++)
        dp[i]=max(dp[i],dp[i-cost]+value);
}
//完全背包

从 0->m 由于物品无限多,放了之后还能放,就不像01一样,必须选择下个物品。也就不用倒过来保证选择状态。

多重背包:

void multiplepack(int cost,int value,int cot)
{
    int k=1;
    while(k<cot)
    {
        zeroonepack(cost*k,value*k);
        cot-=k;
        k<<1;
    }
    zeroonepack(cost*cot,value*cot);
}
//多重背包

不能装满背包,最基本的思想就是把每个物品进行01背包,不过要是物品超过100万,甚至更大呢?

这时候就要分解物品。但是又要保证 小于 其数量的 都 尝试装过。需要用二进制的策略以减少时间复杂度。

比如 17 个物品,分解成 1,2,4,8,(17-8-4-2-1)=2;

分解后的五个物品分别为:1,2,2,4,8。

如果选择 比 17 小的物品装包 分别为:

1=1;

2=2;

3=2+1;

4=2+2;

5=2+2+1;

6=4+2;

7=4+2+1;

……

17=1+2+2+4+8;

这样不会存在遗漏选择 某个数量的物品装包 的可能性。

然后把分组后的 五个物品 进行01背包。

最后贴上大概可以通用的代码:

#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<iostream>
#include<list>
#include<set>
#include<cmath>
#define INF 0x7fffffff
#define eps 1e-6
#define LL long long
using namespace std;

int n,m;
//物品种类 和 背包容量
int dp[10001];
//背包不同状态的价值
int cost[1001],value[1001],cot[1001];
//费用,价值,数量
void zeroonepack(int cost,int value)
{
    for(int i=m;i>=cost;i--)
        dp[i]=max(dp[i],dp[i-cost]+value);
}
//01背包
void completepack(int cost,int value)
{
    for(int i=cost;i<=m;i++)
        dp[i]=max(dp[i],dp[i-cost]+value);
}
//完全背包
void multiplepack(int cost,int value,int cot)
{
    int k=1;
    while(k<cot)
    {
        zeroonepack(cost*k,value*k);
        cot-=k;
        k<<1;
    }
    zeroonepack(cost*cot,value*cot);
}
//多重背包
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=0;i<n;i++)
            scanf("%d%d%d",&cost[i],&value[i],&cot[i]);

        memset(dp,0,sizeof(dp));

        for(int i=0;i<n;i++)
        {
            if(cot[i]==1)
                zeroonepack(cost[i],value[i]);
            else if(cot[i]*cost[i]>=m)
                completepack(cost[i],value[i]);
            else
                multiplepack(cost[i],value[i],cot[i]);
        }
        int ans=0;
        for(int i=0;i<=m;i++)
            //printf("%d ==\n",dp[i]);
        ans=max(ans,dp[i]);
        printf("%d\n",ans);
    }
}

至于背包九讲后面的五个内容,咱还是觉得体会一下就好,不深入了。

接下来就是没看完的图论了,网络流!我来了……

背包的自我修养

时间: 2024-10-12 09:07:03

背包的自我修养的相关文章

一个程序员的自我修养

在网上看到一篇程序员的自我修养,深以为然,不禁摘录一些,勉励自己 一个好的开发人员,应该能够全面.高效.严谨的去处理任何软件程序和业务问题,成为一个好的开发,是一个很有意思的话题,不过无论这个话题如何开展,基础两个字必不可少,虽然代码量是衡量开发能力的重要指标,但仅能够熟练的进行代码编写是不够的,更要能深刻的理解技术原理和业务逻辑,扎实的个人基础和技术基础往往会促进代码的编写,更游刃有余的解决问题. 下面说的一些基础,可能绝大部分开发人员都不会在意甚至忽略,但恰恰这些才是开发大厦的基石. 1.科

程序员的自我修养:(1)目标文件

程序员的自我修养:(1)目标文件 1.目标文件 1.1 编译与链接 在使用像Visual Studio或Qt Creator等IDE时,通常有一个叫做"构建"的按钮.当编辑完成要运行和测试时点一下它,程序就能跑起来了,所以我们很少关心编译和链接.其实,编译和链接合并在一起就称为 构建(Build).简单的一次按键,实际背后却是异常复杂的过程: 预编译(Preprocessing) 编译(Compilation) 扫描:算法类似有限状态机(FSM),将字符转换成Token. 语法分析:分

程序员的自我修养 学习笔记(1)

本文源自在学习<程序员的自我修养>中的心得体会. 对于底层系统程序开发者来说,硬件平台可以抽象为三个主要部件,CPU.内存.I/O控制器. 早期的计算机没有复杂的图形功能,CPU和内存之间的频率差异不大,它们都是连接在同一个bus上面的.其他I/O设备,诸如显示设备.键盘.磁盘等速度比内存.CPU慢很多.为了IO设备与CPU.内存之间的协调通讯,一般每个IO设备商都有相应的IO控制器,早期的硬件结构图如下: 随着技术的进步,CPU的频率越来越高,内存跟不上CPU的速度,他们之间就需要一个转换机

《裸辞的程序猿漂流记二十》——备胎的自我修养一

首先向广大的猿们,表示深深的歉意:楼主由于有事耽搁了,迟来的更新.. 不知道为神马,今天感觉好开心,和妹子一起去麦当劳了,感觉到现在心都扑通扑通的跳啊!!!详细见后节.. 其次感谢广大围观的猿友们,小猿在此表示深深的敬意:感谢soledadzz 给博主上榜的机会,感谢积极评论的猿友们的大力支持,以致于让博主有更博的动力.. 下面,回到正文,首先打开QQ音乐播放器,输入"陈奕迅 时光隧道",Music起,CSDN 貌似不可以放点Music..要是能加个音乐播放器就酷毙了:来点Music

一个前端的自我修养

①一个前端的自我修养 今天给大家分享的主题是前端的自我成长,这是一个关于成长的话题. 很多人都有这样的感觉:听了很多技术圈子的分享,有的有深度,有的循循善诱,深入浅出,但是呢,几年下来,到底哪些用上了,哪些对自己真的有帮助了?反而有些模糊. 2015 年我在不同的场合分享了很多内容:有移动端的性能.有适配.有 Web vs Native,也有 hybrid,但是其实我一直比较担心,真正有深度的内容,其实面向的是比较小众的群体,比如说 Hybrid,其实它在大部分公司里面,是只能用现成的. 所以我

论蒟蒻的自我修养

作为一个蒟蒻,离开大神还有很大一段距离(更不用说神犇了).作为一个想成为SB的SX,自我修养是及其重要的.即使初三老师丧心病狂,也不能放弃这条路恩! 计划: 恩不去MO但是学习他们的那些书~~毕竟数学渣 = ^ = 然后是数据结构...我最弱的一块辣 然后是算法...我也不强 解题思路 啊啊啊!!!差得要命!!! 写程序 啊啊啊!!要死辣!! 所以要多写多练撒!! 要开始刷题了撒!! BZOJ的题目都不会啊!!要死了撒! 估计学一下MO还是有好处的..至少OI MO不分家~~MO主要是数论和排列

程序员的自我修养(一)

程序员的自我修养,最开始看这本书是在学校的图书馆,当时翻了几下,发现这本书内容还真挺特别的.是浙大几个老师写的,就更感觉亲切了,所以自己买了一本书来看看,这也是我到研究生之后买的第一本书了,哈哈,平时都是pdf啥的,其实pdf真不好看. 言归真正,讲讲昨天看到的 从一个HelloWorld程序开始讲起 #include<stdio.h> int main() { printf("helloworld") return 0; } 从高级语言到操作系统可以执行的语言,这里有几个

读《程序员的自我修养》感受

这书不错,链接-装载-库 我觉得是很底层的东西.比如很多人闭着眼睛都能写出来的hello world(当然不包括brianfuck,如果你会,你真的闹残了吗= =), 其实链接编译器做了很多,不然就哪来的printf,这IO初始化也是CRT(c runtime)库完成的.堆栈的初始化,还有系统装载让程序运行等等.涉及很多. 书里后面就讲了一个CRT库,自己写一个,感觉不错,学了很多.比如malloc,free的实现,话说还是跨平台的.当然库很小,功能不多,不过写这个也可以学学算法.内存的分配,这

程序员的自我修养 学习笔记(4)

可执行文件只有装载到内存以后才能被CPU执行.程序就将是菜谱,CPU就像是厨师,计算机的其他硬件就像是厨具,整个炒菜的过程就是一个进程.同样的一份菜谱,不同人可以做出来不同的味道.这个类比真是巧妙. Linux下面,进程最大使用3G的虚拟空间 Windows下面,进程最大使用2G的虚拟空间 现在计算机,配置超过4G的内存的电脑已经不是不可能了,在这种情况下,32位CPU能够访问到大于4G的空间吗?如果此空间指的是虚拟地址空间,由于32位CPU的指针只能是32位,最大寻址范围是0~4GB.如果此空