物件捆绑背包问题:给定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

物件捆绑 背包问题 动态规划 求解相关推荐

  1. 01背包问题 动态规划求解方法 动态方程的详细解释 能理解的解释(附python代码)

    01背包问题属于组合优化问题:假设你要出门旅游,你现在有一个书包,这个书包的容量(capacity)有限,有很多物品如牙刷.防晒霜.雨伞.水杯等等,但书包装不下所有物品,因此我们必须有所取舍.那么通常 ...

  2. 0/1背包问题-----动态规划求解

    问题描述 有n个物品和一个容量为c的背包,从n个物品中选取装包的物品.物品i的重量为w[i],价值为p[i].一个可行的背包装载是指,装包的物品总重量不超过背包的重量.一个最佳背包装载是指,物品总价值 ...

  3. 01背包问题—动态规划求解

    动态规划 01 背包问题 关键代码 for (int i = 1; i <= n; ++i){for (int j = 0; j <= c; ++j){if (j < w[i]) / ...

  4. 1008-----算法笔记----------0-1背包问题(动态规划求解)

    1.问题描述 给定n种物品和一个背包,物品i的重量是wi,其价值为vi,背包的容量为C.问:应该如何选择装入背包的物品,使得装入背包中物品的总价值最大? 2.问题分析 上述问题可以抽象为一个整数规划问 ...

  5. 01背包问题的动态规划求解及其C++实现

    本文讲解01背包问题的动态规划求解,并使用C++进行了实现 文章目录 01背包问题 动态规划 01背包问题的动态规划求解 01背包问题的动态规划求解-C++实现 01背包问题 有nnn个物品,这些物品 ...

  6. 背包问题-动态规划java实现代码

    背包问题-动态规划 目录 背包问题-动态规划 一.动态规划的原理 二.分析与代码实现 1.分析 2.代码分析 一.动态规划的原理 动态规划(dynamic programming)是运筹学的一个分支, ...

  7. 0/1背包问题——动态规划、回溯、分支限界法对比

    0/1背包问题--动态规划.回溯.分支限界法对比 2017.12.19 20:42:02 字数 3713 阅读 2820 目录 1.问题描述 1.1 问题描述 1.2 问题的数学表示(规划类问题,此种 ...

  8. python实现动态规划求解给定矩阵的和最大的子数组(矩阵中数字正负均存在)

    本篇博文比较简单没有太多实际意义,只是为了练习一下,动态规划我并不熟悉,也是刚处于学习的阶段. 问题: 给定一个指定的矩阵,维数小于1000,在矩阵的所有子数组中寻找具有最大和的子数组求和输出. 思路 ...

  9. 子串、子数组与子序列类型问题的动态规划求解(Leetcode题解-Python语言)

    一般来说,子串和子数组都是连续的,而子序列是可以不连续的,遇到子序列问题基本上都是用动态规划求解. 53. 最大子数组和(剑指 Offer 42. 连续子数组的最大和) class Solution: ...

  10. python用动态规划求删除路径_Python | 动态规划求解TSP

    解题思路主要有两部分: i为当前节点(城市),S为还没有遍历的节点(城市集合),表示从第i个节点起,经历S集合中所有的点,到达终点的最短路径长度. 回溯找到最优的路径,需要将S集合一一对应一个数字(类 ...

最新文章

  1. nginx http 服务器搭建
  2. 什么是二进制数 为什么用二进制数表示计算机信息?
  3. SAP MM 物料主数据分类视图的数据会带入批次分类视图里?
  4. 俄罗斯方块(结对作业)
  5. 惜分飞oracle,惜分飞 - 提供7*24专业数据库(Oracle,SQL Server,MySQL等)恢复和Oracle技术服务@Tel:+86 13429648788...
  6. redis命令-key操作
  7. postgres 判断null_PostgreSQL NULLIF()用法及代码示例
  8. 更改数据库管理员sa账户密码
  9. “算法天团”最强课程笔记已整理好,速查收!【附PPT打包下载】
  10. psychopy 音频时长代码_多媒体之音频输入1
  11. 从Demo到Engine(二) -- Render Queue Sort
  12. leetcode [53]最大子序和/Maximum Subarray C++ 暴力解法和贪心解法
  13. macOS的Fn键实用技巧
  14. TakeColor 屏幕取色器 8.0 中文绿色版
  15. html font文本颜色 字体 大小标签元素
  16. 电脑白屏,“笔记本电脑开机白屏的原因和解决方法”的解决方案
  17. [codeforces 1379B] Dubious Cyrpto 公式推导
  18. 获取历史和实时股票数据接口
  19. 测试用例------用户登录(很详细哦)
  20. MINIO_ACCESS_KEY and MINIO_SECRET_KEY are deprecated,Please use MINIO_ROOT_USER and MINIO_ROOT_PASSW

热门文章

  1. 一段经典的 Java 风格程序 ( 类,包 )
  2. 【Java学习笔记】数组的相关事项
  3. SQLite 时间函数
  4. 十一种值得女生交往的男生
  5. web项目继承ServletContainerInitializer进行访问HttpServlet(WebServlet)
  6. Qt qss问题总结
  7. 【深拷贝VS浅拷贝】------【巷子】
  8. 19_debug断点调试
  9. ARC对象内存管理以及强弱指针
  10. MySQL二进制包安装简略过程