物件捆绑 背包问题 动态规划 求解
物件捆绑背包问题:给定N元钱,要购买一些器件。器件有主件和附件之分,也即主件可以单独购买,然而购买附件必须购买对应的主件。下表就是一些主件与附件的例子:
主件 | 附件 |
电脑 | 打印机、扫描仪 |
书柜 | 图书 |
书桌 | 台灯 |
工作椅 | 无 |
把每件物品规定一个重要度,分为5等:用整数1~5表示,第5等最重要。在花费不超过N元(可以等于N元)的前提下,使每件物品的价格与重要度的乘积的总和最大。设第j件物品的价格为v[j],重要度为p[j],共选中了k件物品,编号依次为j1,j2,……,jk,则所求的总和为:v[j1]*p[j1]+v[j2]*p[j2]+ …+v[jk]*p[jk]。
输入
第1行,为两个正整数,用一个空格隔开:N m
从第2行到第m+1行中,第j行给出了编号为j-1的物品基本数据,每行有3个非负整数: v p q(v:物品价格,p:物品重要度,q:主件还是附件。q=0为主件;q>0为附件,q是所属主件的编号)
输出
输出为不超过总钱数的物品的价格与其重要度乘积的总和的最大值。
动态规划求解:
1)思路:同一般的背包问题不同的是,在购买附件的同时必须要购买相应的主件。我们需要对主,附件做捆绑。每一种捆绑结果作为一种购买方式,之后同一般的背包问题
例如:主件A,有附件B、附件C,则由数理统计的知识可知有4中购买方式,即(A,A+B,A+C,A+B+C)。
附件个数为n-1时的购买方式个数为:
2)主附件捆绑的数据结构选择:
因为一件附件只有一个主件,为了捆绑的方便性,可以采用链表的形式。主件为头结点,拉链为附件节点。如下所示:
3)问题求解
#include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct node {int price; ///价格int priority; ///重要程度struct node *next; }Node;typedef struct ///拉链数据结构 {Node num[60]; }List;int dp[360][32001]; int pos; ///用于标记数量 int n,m; ///总钱数和物品数void input(List*); ///物件情况输入,并构造主附件捆绑的数据结构(拉链法) void preDP(List*); ///进行主附件的捆绑 void exeDP(int,int); ///执行动态规划int main() {List list;while(scanf("%d %d",&n,&m)!=EOF){input(&list);preDP(&list);printf("%d\n",dp[m][n]);}return 0; }void input(List* list) {int i;int v,p,q; ///分别代表价格,重要程度,以及主件的编号Node *tmp;for(i=0;i<m;i++){scanf("%d %d %d",&v,&p,&q);if(q==0) ///主件 {list->num[pos].price=v;list->num[pos].priority=p;list->num[pos].next=NULL;pos++;}else ///附件 {tmp=(Node*)malloc(sizeof(Node));tmp->price=v;tmp->priority=p;tmp->next=list->num[q-1].next; ///使用头叉拉链法list->num[q-1].next=tmp;}} }void preDP(List *list) {int i;int sumv,sumvp;Node *p=NULL,*tmp=NULL;m=-1; ///捆绑物品个数计数,从0开始。for(i=0;i<pos;i++) ///对每个主件开始的链 {sumv=list->num[i].price; ///只包括主件sumvp=list->num[i].price*list->num[i].priority;m++;exeDP(sumv,sumvp);p=list->num[i].next;while(p!=NULL) ///包括主件+附件的情况 {///每次都要带主件sumv=list->num[i].price;sumvp=list->num[i].price*list->num[i].priority;tmp=p;while(tmp!=NULL){sumv=sumv+tmp->price;sumvp=sumvp+tmp->price*tmp->priority;m++;exeDP(sumv,sumvp);tmp=tmp->next;}tmp=p;p=p->next;free(tmp);}} }void exeDP(int sumv,int sumvp) {int i;for(i=0;i<=n;i++){if(m==0){if(sumv>i)dp[0][i]=0;elsedp[0][i]=sumvp;}else{if(sumv>i)dp[m][i]=dp[m-1][i];elsedp[m][i]=dp[m-1][i]>(dp[m-1][i-sumv]+sumvp)? dp[m-1][i]:(dp[m-1][i-sumv]+sumvp);}} }
转载于:https://www.cnblogs.com/xudong-bupt/archive/2013/03/18/2966191.html
物件捆绑 背包问题 动态规划 求解相关推荐
- 01背包问题 动态规划求解方法 动态方程的详细解释 能理解的解释(附python代码)
01背包问题属于组合优化问题:假设你要出门旅游,你现在有一个书包,这个书包的容量(capacity)有限,有很多物品如牙刷.防晒霜.雨伞.水杯等等,但书包装不下所有物品,因此我们必须有所取舍.那么通常 ...
- 0/1背包问题-----动态规划求解
问题描述 有n个物品和一个容量为c的背包,从n个物品中选取装包的物品.物品i的重量为w[i],价值为p[i].一个可行的背包装载是指,装包的物品总重量不超过背包的重量.一个最佳背包装载是指,物品总价值 ...
- 01背包问题—动态规划求解
动态规划 01 背包问题 关键代码 for (int i = 1; i <= n; ++i){for (int j = 0; j <= c; ++j){if (j < w[i]) / ...
- 1008-----算法笔记----------0-1背包问题(动态规划求解)
1.问题描述 给定n种物品和一个背包,物品i的重量是wi,其价值为vi,背包的容量为C.问:应该如何选择装入背包的物品,使得装入背包中物品的总价值最大? 2.问题分析 上述问题可以抽象为一个整数规划问 ...
- 01背包问题的动态规划求解及其C++实现
本文讲解01背包问题的动态规划求解,并使用C++进行了实现 文章目录 01背包问题 动态规划 01背包问题的动态规划求解 01背包问题的动态规划求解-C++实现 01背包问题 有nnn个物品,这些物品 ...
- 背包问题-动态规划java实现代码
背包问题-动态规划 目录 背包问题-动态规划 一.动态规划的原理 二.分析与代码实现 1.分析 2.代码分析 一.动态规划的原理 动态规划(dynamic programming)是运筹学的一个分支, ...
- 0/1背包问题——动态规划、回溯、分支限界法对比
0/1背包问题--动态规划.回溯.分支限界法对比 2017.12.19 20:42:02 字数 3713 阅读 2820 目录 1.问题描述 1.1 问题描述 1.2 问题的数学表示(规划类问题,此种 ...
- python实现动态规划求解给定矩阵的和最大的子数组(矩阵中数字正负均存在)
本篇博文比较简单没有太多实际意义,只是为了练习一下,动态规划我并不熟悉,也是刚处于学习的阶段. 问题: 给定一个指定的矩阵,维数小于1000,在矩阵的所有子数组中寻找具有最大和的子数组求和输出. 思路 ...
- 子串、子数组与子序列类型问题的动态规划求解(Leetcode题解-Python语言)
一般来说,子串和子数组都是连续的,而子序列是可以不连续的,遇到子序列问题基本上都是用动态规划求解. 53. 最大子数组和(剑指 Offer 42. 连续子数组的最大和) class Solution: ...
- python用动态规划求删除路径_Python | 动态规划求解TSP
解题思路主要有两部分: i为当前节点(城市),S为还没有遍历的节点(城市集合),表示从第i个节点起,经历S集合中所有的点,到达终点的最短路径长度. 回溯找到最优的路径,需要将S集合一一对应一个数字(类 ...
最新文章
- nginx http 服务器搭建
- 什么是二进制数 为什么用二进制数表示计算机信息?
- SAP MM 物料主数据分类视图的数据会带入批次分类视图里?
- 俄罗斯方块(结对作业)
- 惜分飞oracle,惜分飞 - 提供7*24专业数据库(Oracle,SQL Server,MySQL等)恢复和Oracle技术服务@Tel:+86 13429648788...
- redis命令-key操作
- postgres 判断null_PostgreSQL NULLIF()用法及代码示例
- 更改数据库管理员sa账户密码
- “算法天团”最强课程笔记已整理好,速查收!【附PPT打包下载】
- psychopy 音频时长代码_多媒体之音频输入1
- 从Demo到Engine(二) -- Render Queue Sort
- leetcode [53]最大子序和/Maximum Subarray C++ 暴力解法和贪心解法
- macOS的Fn键实用技巧
- TakeColor 屏幕取色器 8.0 中文绿色版
- html font文本颜色 字体 大小标签元素
- 电脑白屏,“笔记本电脑开机白屏的原因和解决方法”的解决方案
- [codeforces 1379B] Dubious Cyrpto 公式推导
- 获取历史和实时股票数据接口
- 测试用例------用户登录(很详细哦)
- MINIO_ACCESS_KEY and MINIO_SECRET_KEY are deprecated,Please use MINIO_ROOT_USER and MINIO_ROOT_PASSW