背包问题

luogu4389 付公主的背包

余生长醉 提交于 2020-04-08 05:00:23
题目链接: 洛谷 题目大意:现在有$n$个物品,每种物品体积为$v_i$,对任意$s\in [1,m]$,求背包恰好装$s$体积的方案数(完全背包问题)。 数据范围:$n,m\leq 10^5$ 这道题,看到数据范围就知道是生成函数。 $$Ans=\prod_{i=1}^n\frac{1}{1-x^{v_i}}$$ 但是这个式子直接乘会tle,我们考虑进行优化。 看见这个连乘的式子,应该是要上$\ln$. $$Ans=\exp(\sum_{i=1}^n\ln(\frac{1}{1-x^{v_i}}))$$ 接下来的问题就是如何快速计算$\ln(\frac{1}{1-x^{v_i}})$。 $$\ln(f(x))=\int f'f^{-1}dx$$ 所以 $$\ln(\frac{1}{1-x^v})=\int\sum_{i=1}^{+\infty}vix^{vi-1}*(1-x^v)dx$$ $$=\int(\sum_{i=1}^{+\infty}vix^{vi-1}-\sum_{i=2}^{+\infty}v(i-1)x^{vi-1})dx$$ $$=\int(\sum_{i=1}^{+\infty}vx^{vi-1})dx$$ $$=\sum_{i=1}^{+\infty}\frac{1}{i}x^{vi}$$ 然后就可以直接代公式了。 1 #include<cstdio> 2

4. 多重背包问题 I

心已入冬 提交于 2020-04-01 06:24:09
多重背包问题 I 描述 有 NN 种物品和一个容量是 VV 的背包。 第 ii 种物品最多有 sisi 件,每件体积是 vivi,价值是 wiwi。 求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。 输出最大价值。 输入格式 第一行两个整数,N,VN,V,用空格隔开,分别表示物品种数和背包容积。 接下来有 NN 行,每行三个整数 vi,wi,sivi,wi,si,用空格隔开,分别表示第 ii 种物品的体积、价值和数量。 输出格式 输出一个整数,表示最大价值。 数据范围 0<N,V≤100 0<vi,wi,si≤100 输入样例 4 5 1 2 3 2 4 1 3 4 3 4 5 2 输出样例 10 代码 #include<bits/stdc++.h> using namespace std; const int N = 105; int w[N],v[N],s[N]; int dp[N]; int main(){ int n,m; cin >> n >> m; for(int i = 0; i < n; i++) cin >> v[i] >> w[i] >> s[i]; for(int i = 0; i < n; i++){ for(int j = m; j > 0; j--){ for(int k = 0; k <= s[i] && k * v[i] <=

依赖背包

感情迁移 提交于 2020-03-25 23:41:39
487. 金明的预算方案 思路: 一个商品只能依赖或者被依赖且依赖个数比较小,直接将同一依赖下的物品分组。 #include<iostream> #include<algorithm> #include<cstring> #include<vector> #define v first #define w second using namespace std; typedef pair<int,int> PII; typedef long long LL; const int N=32010,M=70,V=10010; PII master[M]; vector<PII> attach[M]; LL f[N]; int main(){ int n,m; cin>>m>>n; for(int i=1;i<=n;++i){ int v,w,q; cin>>v>>w>>q; if(!q){ master[i]={v,w}; } else { attach[q].push_back({v,w}); } } for(int i=1;i<=n;++i){ if(master[i].w){ for(int j=m;j>=0;--j){ for(int k=0;k<(1<<attach[i].size()) ;++k){ LL vv=master[i].v,ww=master[i].w

多重背包问题II

喜欢而已 提交于 2020-03-23 21:43:31
多重背包问题II 总体积是m,每个小物品的体积是A[i] ,每个小物品的数量是B[i],每个小物品的价值是C[i] 求能够放入背包内的最大物品能够获得的最大价值 和上一个很类似 上一题体积就是价值,这里的价值是单独定义了 状态转移方程 不放A[i] f[i][j] =f[i-1][j] 放A[j] 可放多个设为k, k = min(j/A[i],B[i]) f[i][j] = f[i-1][j- ki*A[i]] + ki*C[i] 0<=ki<=k 取最大值 完全背包问题时候: 0<=ki*A[i]<=m public class Solution { public int backPack(int m, int[] A,int[] B ,int[] C) { // write your code here int[] P = new int[m+1];// P[i][j] 前i个物品放在j的空间中的最大价值 for(int i = 0;i< A.length; i++){ for(int j = m;j>=1;j--){ if(j>=A[i]){ int k = j/A[i];// 该物品最大可以放k个,然而限制条件最大是B[i] k = Math.min(k,B[i]);// 取最小值 while(k>=0){ if(j>=A[i]*k){ P[j] =Math.max(P

贪心算法_01背包问题_Java实现

烈酒焚心 提交于 2020-03-23 20:30:52
原文地址: http://blog.csdn.net/ljmingcom304/article/details/50310789 本文出自:【梁敬明的博客】 1.贪心算法   什么是贪心算法?是指在对问题进行求解时,总是做出当前看来是最好的选择。也就是说,不从整体最优上加以考虑,所得出的结果仅仅是某种意义上的局部最优解。因此贪心算法不会对所有问题都能得到整体最优解,但对于很多问题能产生整体最优解或整体最优解的近似解。 2背包问题     一个旅行者有一个最多能装m公斤的背包,现在有n中物品,每件的重量分别是W1、W2、……、Wn,每件物品的价值分别为C1、C2、……、Cn, 需要将物品放入背包中,要怎么样放才能保证背包中物品的总价值最大? 3.算法分析     当遇到这样的问题,我们可以换一种角度去思考,假设在一个100m3的房子里面,现在要将房子装满,同时要保证放入的物品个数最多以及装入的东西最重,现在身边有铁球和棉花,请问大家是放铁球进去好呢还是放棉花进去好呢?显而易见,放入铁球进去是最优选择。但是原因是什么呢?很简单,就是因为铁球的密度较大,相同体积的铁球和棉花相比,铁球更重。   不过前提是放入第一个铁球时,铁球的体积V1小于等于100m3 ;放入第二个铁球时,铁球的体积V2 小于等于(100-V1)m3;……;放入第n个铁球时,铁球的体积小于等于(100- ∑n1Vn-1

5. 多重背包问题 II 【用二进制优化】

你说的曾经没有我的故事 提交于 2020-03-23 15:22:08
多重背包问题 II 描述 有 NN 种物品和一个容量是 VV 的背包。 第 ii 种物品最多有 sisi 件,每件体积是 vivi,价值是 wiwi。 求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。 输出最大价值。 输入格式 第一行两个整数,N,VN,V,用空格隔开,分别表示物品种数和背包容积。 接下来有 NN 行,每行三个整数 vi,wi,sivi,wi,si,用空格隔开,分别表示第 ii 种物品的体积、价值和数量。 输出格式 输出一个整数,表示最大价值。 数据范围 0<N≤1000 0<V≤2000 0<vi,wi,si≤2000 提示: 本题考查多重背包的二进制优化方法。 输入样例 4 5 1 2 3 2 4 1 3 4 3 4 5 2 输出样例: 10 题解 普通的多重背包会超时,这是用二进制优化的方法 例如 总数是7 可以用二进制优化后 7 = 1 + 2 + 4;那么 1,2, 4就可以表示所有 [1 ,7]的数 例如 总数是10 那么 10 = 1 + 2 + 4 + 3 ,用1,2 ,4,3就可以表示所有【1,10】的数 这样比直接暴力快 代码 #include<bits/stdc++.h> #define pb push_back using namespace std; const int N = 2005; int w[N],v[N]

蓝桥杯算法练习笔记(13)__背包问题

只谈情不闲聊 提交于 2020-03-17 06:30:50
14.背包问题 1.0-1背包问题 例如:有5件物品,体积分别为[2,2,6,5,4],价值分别为[6,3,5,4,6] //0-1背包问题 # include <iostream> # include <cstdio> using namespace std ; int c [ 105 ] ; //每件物品的体积 int w [ 105 ] ; //每件物品的价值 int dp [ 105 ] [ 105 ] ; int main ( ) { int n , v ; //n件物品 最大可用体积为v cin >> n >> v ; for ( int i = 1 ; i <= n ; i ++ ) { cin >> w [ i ] >> c [ i ] ; } for ( int i = 1 ; i <= n ; i ++ ) { //前i个物品 for ( int j = 0 ; j <= v ; j ++ ) { //总重量不超过j if ( j >= c [ i ] ) { // 最大价值 dp[i][j] dp [ i ] [ j ] = max ( dp [ i - 1 ] [ j - c [ i ] ] + w [ i ] , dp [ i - 1 ] [ j ] ) ; } else { //不放,继承上一次数据 dp [ i ] [ j ] = dp [ i - 1

动态规划算法(@背包问题)

早过忘川 提交于 2020-03-14 08:24:01
 动态规划(Dynamic programming)是一种在数学、计算机科学和经济学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。 动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。    动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再合并子问题的解以得出原问题的解。 通常许 多 子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量: 一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同 一个 子问题解之时直接查表。 这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。   关于动态规划最经典的问题当属背包问题。 算法步骤: 1. 最优子结构性质。如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质(即满足最优化原理)。最优子结构性质为动态规划算法解决问题提供了重要线索。 2. 子 问题重叠性质。子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多 次。 动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题 时,只是 在表格中简单地查看一下结果

算法:零一背包问题

安稳与你 提交于 2020-03-12 12:44:49
零一背包问题是一个非常重要的动态规划求解的问题,只要你学习DP就不可不学零一背包,所以务必要认真学习这个问题。 例题 hdu2602 Bone Collector 题目描述: "骨头收集者"带着体积V的背包去捡骨头,已知每个骨头的体积和价值,求能装进背包的最大价值。N <= 1000, V <= 1000。 输入格式: 第一行:是测试数据。 接下来对于每组测试数据,第一行是骨头数量和背包体积,第二行是每个骨头的价值,第三行是每个骨头的体积。 输出格式: 一个整数,为最大价值总和是多少。 输入样例: 1 5 10 1 2 3 4 5 5 4 3 2 1 输出样例: 14 零一背包问题 看到这道题,想想暴力、贪心貌似都不行,那么此时就要来dp了。而提到DP,就一定就要去想:状态、转移方程、初值和答案了。 状态:dp[i] [j]指到第i个物品,重量为j时,价值总和的最大值。 转移方程:dp[i] [j] = max(dp[i - 1] [j], dp[i - 1] [j - w[i]] + v[i]) 其实这个的意思就是:分两种情况讨论,如果说不选这第i个物品,那么直接把dp[i] [j] = dp[i - 1] [j]就行了,但是如果说选这个物品,那么就得分析一下了,先看重量:要找dp[i] [j],就必然是由dp[i] [j - w[i]]推过来的,而不是dp[i] [j + w

HDU 1248(寒冰王座)

ぃ、小莉子 提交于 2020-03-11 03:30:26
基础的 0-1背包问题,将背包的重量作为背包的价值,套用模板即可。 #include <iostream> #include <algorithm> using namespace std; const int MAXN = 10005; int dp[MAXN]; //背包的价值,dp[i]表示背包容量为i时,背包的最大价值 int main() { int value[3] = { 150,200,350 }; //三种货物的价值 int T; int N; cin >> T; while (T--) { cin >> N; memset(dp, 0, sizeof(dp)); for (int i = 0; i < 3; i++) //0-1背包模板 { for (int j = value[i]; j <= N; j++) dp[j] = max(dp[j], dp[j - value[i]] + value[i]); } cout << N - dp[N] << endl; } return 0; } 继续加油。 来源: CSDN 作者: Intelligence1028 链接: https://blog.csdn.net/Intelligence1028/article/details/104746614