完全背包问题实例

题目描述

零崎有很多朋友,其中有一个叫做lfj的接盘侠。

lfj是一个手残,他和零崎一起玩网游的时候不好好打本,天天看拍卖行,没过多久,就成为了一个出色的商人。时间一长,虽然挣了不少钱,却没时间练级了。

作为lfj的友人,零崎实在看不下去,于是他决定帮lfj一把。当然了,零崎肯定不会自己动手,活还得你们来干。

lfj可以提供给你们拍卖行所有能买到物品的价格和利润,由于游戏产出不限,所以可以假定只要有钱,即使是同一种东西,多少个也都能买到手。lfj还会告诉你他初始的成本。虽然零崎想让你们给出一次交易中利润最大的购买方案,但是lfj觉得只要知道最大利润就可以了。

输入

每组数据第一行为两个整数P和N,表示本金和拍卖行物品种类数。

接下来N行,每行两个数据pi,ci代表第i类物品的利润和购买价格。

1<=P<=20000,1<=N<=300,1<=c,p<=200

输出

对于每组数据,输出一行,为能获得的最大利润

输入样例

3 1
2 1
2 3
1 1
1 2
2 1

输出样例

6
4

Hint

使用if直接比较不要调用max()以防超时

完全背包问题:

完全背包和0-1背包的不同之处:完全背包的物品不再是只有一件而是有无数件,所以对于某一件物品也不再是拿(1)不拿(0)。而是变为了拿0件,1件,2件...k件,按照0-1背包问题的状态转移方程同样可以写出完全背包的状态转移方程:

f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k*c[i]<=v}

分析上述的状态转移方程

这跟01背包问题一样有O(N*V)个状态需要求解,但求解每个状态的时间已经不是常数了,求解状态f[i][v]的时间是O(v/c[i]),总的复杂度是超过O(VN)的。

因此我们需要对改状态方程进行改进:

O(VN)的算法:

1 for (int i = 1; i <= N; i++)
2
3     for (int v = 0; v <= V; v++)
4
5        f[v] = max(f[v], f[v - c[i]] + w[i]);

或者f[i][v]=max(f[i-1][v],f[i][v-c[i]]+w[i])

可以发现和0-1背包不同的地方只是在于内部for循环的起止改变了顺序,为什么这样可以实现完全背包的要求呢?

首先想想为什么P01中要按照v=V..0的逆序来循环。这是因为要保证第i次循环中的状态f[i][v]是由状态f[i-1][v-c[i]]递推而来。换句话说,这正是为了保证每件物品只选一次,保证在考虑“选入第i件物品”这件策略时,依据的是一个绝无已经选入第i件物品的子结果f[i-1][v-c[i]]。而现在完全背包的特点恰是每种物品可选无限件,所以在考虑“加选一件第i种物品”这种策略时,却正需要一个可能已选入第i种物品的子结果f[i][v-c[i]],所以就可以并且必须采用v= 0..V的顺序循环。这就是这个简单的程序为何成立的道理。

因此可以得到完全背包的代码实现:

1 void CompletePack(int cost , int weight)
2 {
3     for (int i = weight ; i <= W ; ++ i)
4         f[i] = max(f[i],f[i-weight]+cost) ;
5 }

下面给出本题的代码实现:

 1 #include <bits/stdc++.h>
 2 long long f[20010];
 3 long long c[310];
 4 long long v[310];
 5 using namespace std;
 6
 7 int main()
 8 {
 9     int V,k;
10     while(~scanf("%d%d",&V,&k))
11     {
12         memset(f,0,sizeof(f));
13         memset(c,0,sizeof(c));
14         memset(v,0,sizeof(v));
15         for(int i=1; i<=k; i++)
16             scanf("%lld%lld",&v[i],&c[i]);
17         for(int i=1; i<=k; i++)
18         {
19             for(int j=c[i]; j<=V; j++)
20             {
21                 if(f[j-c[i]]+v[i]>=f[j])
22                     f[j]=f[j-c[i]]+v[i];
23                 else
24                     f[j]=f[j];
25             }
26         }
27         printf("%lld\n",f[V]);
28     }
29 }
时间: 2024-10-12 14:50:30

完全背包问题实例的相关文章

学习日志---动态规划(背包问题)

背包问题: 利用动态矩阵的方式,一步一步在前一次有最优解的时候,推断后面的最优解 核心: bestValues[i][j] = Math.max(bestValues[i - 1][j],                                 ivalue + bestValues[i - 1][j - iweight]); i是指商品,[i]是指前i个,v是指背包可容纳的重量,节点值是指最优的价值数. 因为加了一个i,最优解要么就是有i,要么就是没有i. 摘自:http://www.

0/1背包问题的动态规划法求解 —— Java 实现

0/1背包问题的动态规划法求解,前人之述备矣,这里所做的工作,不过是自己根据理解实现了一遍,主要目的还是锻炼思维和编程能力,同时,也是为了增进对动态规划法机制的理解和掌握. 值得提及的一个问题是,在用 JAVA 实现时, 是按算法模型建模,还是用对象模型建模呢? 如果用算法模型,那么 背包的值.重量就直接存入二个数组里:如果用对象模型,则要对背包以及背包问题进行对象建模.思来想去,还是采用了对象模型,尽管心里感觉算法模型似乎更好一些.有时确实就是这样,对象模型虽然现在很主流,但也不是万能的,采用

Python实现Wordcloud生成词云图的示例

wordcloud是Python扩展库中一种将词语用图片表达出来的一种形式,通过词云生成的图片,我们可以更加直观的看出某篇文章的故事梗概. 首先贴出一张词云图(以哈利波特小说为例): 在生成词云图之前,首先要做一些准备工作 1.安装结巴分词库 pip install jieba Python中的分词模块有很多,他们的功能也都是大同小异,我们安装的结巴分词 是当前使用的最多的类型. 下面我来简单介绍一下结巴分词的用法 结巴分词的分词模式分为三种: (1)全模式:把句子中所有的可以成词的词语都扫描出

《算法导论》读书笔记之第16章 0-1背包问题—动态规划求解

原文:http://www.cnblogs.com/Anker/archive/2013/05/04/3059070.html 1.前言 前段时间忙着搞毕业论文,看书效率不高,导致博客一个多月没有更新了.前段时间真是有些堕落啊,混日子的感觉,很少不爽.今天开始继续看算法导论.今天继续学习动态规划和贪心算法.首先简单的介绍一下动态规划与贪心算法的各自特点及其区别.然后针对0-1背包问题进行讨论.最后给出一个简单的测试例子,联系动态规划实现0-1背包问题. 2.动态规划与贪心算法 关于动态规划的总结

利用回溯法求解背包问题

最近看完了利用回溯法求八皇后问题,最后成功求解到92种解法,然后在看利用贪心求解背包问题,突然想到其实也可以利用回溯法求解背包问题,本质上回溯法是一个穷举的方式在求. 回溯法求解出的结果肯定是正确的,这也可以验证自己所写的贪心算法的正确性. 问题描诉: 设定Wmax为最大重量,W[](0~n-1)为编号0~n-1的货物重量,V[](0~n-1)为其价值,x[]为其中解, 在wn=ΣXi*Wi<Wmax的条件下,求Vmax=ΣXi*Vi. 代码如下: //全局变量最大价值int maxvalue=

背包问题-01背包

*/--> 背包问题-01背包 Table of Contents 1 问题描述 2 问题思路 2.1 问题定义 2.2 实例演讲 3 问题思考 3.1 优化-定义问题 3.1.1 索引的改变 3.1.2 顺序的改变 3.2 优化-复杂度 3.3 初始值的思考 4 问题延伸 4.1 01背包问题的其他解法 4.2 01背包问题的实际引用 5 参考阅读 1 问题描述 背包问题主要分为三种:01背包 完全背包 多重背包. 01背包就是本文要讨论的问题. 有N件物品和一个容量为W的背包,每种物品 均只

[C++] 贪心算法之活动安排、背包问题

一.贪心算法的基本思想 在求解过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解. 从贪心算法的定义可以看出,贪心算法不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解.如果一个问题可以同时用几种方法解决,贪心算法应该是最好的选择之一. 二.贪心算法的基本要素 (1)最优子结构性质 (2)贪心选择性质(局部最优选择) 三.贪心算法实例 1.活动安排 设有n个活

贪心法——活动选择问题和背包问题

今天上午听了米老师讲的算法,感觉收获很多,对于算法更加有信心了.首先,先来宏观看一下: 这三种算法总的来说,刚开始看的时候不知道怎么下手,但是看多了也会有那么一点儿感觉.分治法是这三种算法里面都有的思想,动态规划和贪心都是将问题分解成子问题求解,但动态规划里面的子问题都带有联系,而贪心算法里面的子问题都相对独立,唯一不同的是,贪心算法要首先想出一个解决方案来构造求解最优解的过程. 宏观介绍下算法后,来看看贪心算法的两个实例. 一,活动选择问题 解决方案: 对于活动的选择问题,我们求解过程是这样的

01背包问题:

01背包问题: 1.递归思想 0- 1 背包问题如果采用递归算法来描述则非常清楚明白, 它的算法根本思想是假设用布尔函数knap( s, n) 表示n 件物品放入可容质量为s 的背包中是否有解( 当knap 函数的值为真时 说明问题有解,其值为假时无解) . 我们可以通过输入s 和n 的值, 根据它们的值可分为以下几种情况讨论: ( 1) 当s= 0时可知问题有解, 即函数knap( s, n) 的值为true; ( 2) 当s< 0 时这时不可能, 所以函数值为false; ( 3) 当输入的