机试算法讲解: 第54题 0-1背包之如何采药
来源:互联网 发布:htpc必备软件 编辑:程序博客网 时间:2024/05/22 08:16
/*背包:种类:0-1背包,完全背包,多重背包。 0-1背包:含义:有一个容量为V的背包和物品,物品与两个属性,体积W和价值V,每种物品只有1个。 要求用这个背包装下价值尽可能多的物品,求该最大价值,背包可以不被装满。 特点:每个物品至多能选1件,物品数量只有0和1两种情况。 dp[i][j]:表示总体积不超过j的情况下,前i个物品所能达到的最大价值 初始化:dp[0][j]=0(0<=j<=s) 关键:采用逆序循环,保证更新dp[j]时,dp[j-list[i].w]是没有放入物品i时的数据dp[i-1][j-list[i].w]状态未因为本次更新发生改变 for(i = 1 ; i <= n ; i++) {for( j = s ;j >= list[i].w ; j++){dp[j] = max{dp[j],dp[j-list[i].w]+list[i].v}} }0-1背包变体:dp[i][j]:前i个物品总体积恰好为v时所能达到的最大价值,只需改动初始化:dp[0][0]=0,其他dp[0][j]均为负无穷或不存在 完全背包:一个容积为V的背包,同时有n个物品,每个物品均有各自的体积W和价值v,每个物品的数量均为无限个,求试用该背包最多能装的物品价值总和。 改动代码:每个物品可以被无限次选择,那么状态dp[i][j]恰好可以由可能已经放入物品i的状态dp[i][j-list[i].w]转移而来,所以这里将状态的遍历顺序变为 顺序,使在更新状态dp[j]时,dp[j-list[i].w]可能因为放入物品i而发生改变。 for(i = 1 ; i <= n ; i++) {for(j = list[i].w ; j <= s ; j++){dp[j] = max{dp[j],dp[j-list[i].w]+list[i].v}} }问题:采药。不同草药,采每一株需要一些时间,每一株有自己价值,如何让采到的价值最大。输入:第一行有两个整数T(1<=T<=1000)和M(1<=M<=100),T代表总共能够用来采药的时间,M代表山洞里的草药数目。 接下来的M行,每行包括两个在1到100之间(包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值输出:在规定时间内,可以猜到的草药的最大总价值输入:70(T采药总时间) 3(M,M行,每行是采药时间和价值)71 10069 11 2输出:3思路:0-1背包:每个物品装或者不装(背包中有0个或者1个该物品)。这里总共时间=容积,物品体积=采摘每个草药时间。 用dp[i][j]:表示总体积不超过j的情况下,前i个物品所能达到的最大价值。初始时:dp[0][j](0<=j<=V)=0。每个状态有2个状态转移来源。 若物品i放入背包,体积为w,价值为v,则dp[i][j] = dp[i-1][j-w]+v。即在总体积不超过j-w时,前i-1件物品可组成的最大价值的基础上再 加上i物品的价值v。若物品不加入背包,则dp[i][j]=dp[i-1][j]。状态转移方程:dp[i][j] = max{dp[i-1][j-w]+v,dp[i-1][j]};注意:j-w的值是否为负值,若为负,则转移来源能被转移。目标状态:dp[n][s]关键:1 0-1背包状态转移方程:dp[i][j] = max{dp[i-1][j-w]+v,dp[i-1][j]};,用 j >= list[i].w作区分,优化后的转移方程:dp[j] = max{dp[j-w]+v,dp[j]}2 目标状态是:dp[n][s],s是总容量,n是物品总数3 必须声明一个结构list:v,w表示价值和体积4 倒序遍历j,保证确定dp[j]的值时,dp[j-list[i].w]的值尚未被修改5 0-1背包复杂度=状态数量*状态转移复杂度=(物品数量n*背包总容积s)*O(1)=O(n*s),优化过后空间复杂度为O(s)*/#include <stdio.h>#include <stdlib.h>#include <string.h>//定义背包typedef struct List{int w;//体积int v;//价值}List;int max(int a,int b){return a > b ? a:b;}int main(int argc,char* argv[]){int s;//总容积int n;//n行int i,j;while(EOF!=scanf("%d %d",&s,&n)){List list[101];//int dp[101][1001];int dp[1001];//优化for(i = 1 ; i <= n ; i++){scanf("%d %d",&list[i].w,&list[i].v);}//初始化状态量for(i = 0 ; i <= s ; i++){//dp[0][i] = 0;dp[i] = 0;}//对于时间足够的情况,状态来源是:dp[i][j]为两者之中的最大值for(i = 1 ; i <= n ; i++){for(j = s; j >= list[i].w ; j--){//dp[i][j] = max(dp[i-1][j],dp[i-1][j-list[i].w] + list[i].v);//优化:必须倒序更新每个dp[j]的值,j小于list[i].w的各dp[j]不做更新,保持原值,即等价与dp[i][j] = dp[i-1][j]dp[j] = max(dp[j],dp[j-list[i].w] + list[i].v);}/*for(j = list[i].w-1; j >= 0 ; j--){dp[i][j] = dp[i-1][j];}*/}//printf("%d\n",dp[n][s]);printf("%d\n",dp[s]);}system("pause");getchar();return 0;}
0 0
- 机试算法讲解: 第54题 0-1背包之如何采药
- 0-1 背包之采药
- 机试算法讲解: 第55题 完全背包之储蓄罐最少放了多少钱
- 采药【(0-1)背包问题】
- 【Tyvj1005 采药】0-1背包
- 采药(0/1背包)
- 机试算法讲解: 第42题 广度优先搜索之我该如何倒可乐
- 机试算法讲解:第47题 递推之N阶楼梯如何上楼
- 机试算法讲解: 第53题 动态规划之如何摆放橘子
- 机试算法讲解: 第56题 多重背包之一起支援灾区
- [sicily online]1146. 采药(0-1背包)
- 采药---0-1背包型dp
- 0-1背包:nefu19采药hdu2546饭卡
- (ssl1045)P1048 采药(0/1背包)
- 0-1背包问题(采药)
- 机试算法讲解: 第12题 贪心之我该如何选择:跑男,爸爸去哪儿,好声音,极限挑战
- 机试算法讲解:第2题 结构体之快速排序
- 机试算法讲解: 第11题 贪心之猫鼠大战
- 树莓派的简单应用
- linux的socket_tcp服务端与 linux的socket_tcp客服端简单通讯
- 卫计委电子病历架构基本概念
- 手把手教你学Android-开发环境的搭建
- 繁复的的个梵蒂冈大概发的广佛
- 机试算法讲解: 第54题 0-1背包之如何采药
- Java 多线程 并发编程
- php通过pdo连接mssql
- hdu 5122 K.Bro Sorting
- Spring MVC 中 HandlerInterceptorAdapter的使用
- Java对Map排序
- LeetCode-Linked List Cycle II
- NSNotificationCenter 通知中心实现传值
- [二分]poj3104 Drying