多重背包问题
来源:互联网 发布:seo关键字是什么 编辑:程序博客网 时间:2024/05/17 18:18
多重背包模板:
#include <iostream>#include <stdio.h>#include <string.h>#define N 1000 //物品个数 #define M 100000000 //所有物品可能的最大价值 using namespace std;int m[N],c[N],w[N],f[M];int V;int max(int a,int b){return a>b?a:b;}void ZeroOnePack(int cost,int weight){ int v; for(v=V;v>=cost;v--) f[v]=max(f[v],f[v-cost]+weight);}void CompletePack(int cost,int weight){ int v; for(v=cost;v<=V;v++) f[v]=max(f[v],f[v-cost]+weight);}void MultiplePack(int cost,int weight,int amount){ int k; if(cost*amount>=V) { CompletePack(cost,weight); return; }/* 二进制优化 k=1; while(k<amount) { ZeroOnePack(k*cost,k*weight); amount=amount-k; k=k*2; } ZeroOnePack(amount*cost,amount*weight);*/}int main(){ int n,i; scanf("%d %d",&n,&V); // 两种不同的初始化方式,根据情况自行选择 //memset(f,0,sizeof(f[0])*(V+1)); // 只希望价格尽量大 //memset(f,-M,sizeof(f[0])*(V+1));f[0]=0; // 要求恰好装满背包 for(i=0;i<n;i++) scanf("%d %d %d",m+i,c+i,w+i); for(i=0;i<n;i++) MultiplePack(c[i],w[i],m[i]); printf("%d\n",f[V]); return 0;}
比直接拆成一件一件物品的01背包省时间,因为多了一步二进制优化拆解 (例子节选自网络)
假如给了我们 价值为 2,但是数量却是10 的物品,我们应该把10给拆开,要知道二进制可是能够表示任何数的,所以10 就是可以有1,2, 4,8之内的数把它组成,一开始我们选上 1了,然后让10-1=9,再选上2,9-2=7,在选上 4,7-4=3,而这时的3<8了,所以我们就是可以得出 10由 1,2,4,3,来组成,就是这个数量为1,2,3,4的物品了,那么他们的价值是什么呢,是2,4,6,8,也就说给我们的价值为2,数量是10的这批货物,已经转化成了价值分别是2,4,6,8元的货物了,每种仅有一件。这就是二进制优化的思想。
假如给了我们 价值为 2,但是数量却是10 的物品,我们应该把10给拆开,要知道二进制可是能够表示任何数的,所以10 就是可以有1,2, 4,8之内的数把它组成,一开始我们选上 1了,然后让10-1=9,再选上2,9-2=7,在选上 4,7-4=3,而这时的3<8了,所以我们就是可以得出 10由 1,2,4,3,来组成,就是这个数量为1,2,3,4的物品了,那么他们的价值是什么呢,是2,4,6,8,也就说给我们的价值为2,数量是10的这批货物,已经转化成了价值分别是2,4,6,8元的货物了,每种仅有一件。这就是二进制优化的思想。
那为什么会有完全背包和01 背包的不同使用加判断呢?
①当数据很大,大于背包的容纳量时,我们就在这个物品中取几件,取得量未知,就理解为无限
②小于容纳量的就转化为01背包来处理,省时间。(用二进制优化,不要拆分一件一件一般都会超时)
例题:POJ1014
Dividing
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 71475 Accepted: 18637
Description
Marsha and Bill own a collection of marbles. They want to split the collection among themselves so that both receive an equal share of the marbles. This would be easy if all the marbles had the same value, because then they could just split the collection in half. But unfortunately, some of the marbles are larger, or more beautiful than others. So, Marsha and Bill start by assigning a value, a natural number between one and six, to each marble. Now they want to divide the marbles so that each of them gets the same total value. Unfortunately, they realize that it might be impossible to divide the marbles in this way (even if the total value of all marbles is even). For example, if there are one marble of value 1, one of value 3 and two of value 4, then they cannot be split into sets of equal value. So, they ask you to write a program that checks whether there is a fair partition of the marbles.
Input
Each line in the input file describes one collection of marbles to be divided. The lines contain six non-negative integers n1 , . . . , n6 , where ni is the number of marbles of value i. So, the example from above would be described by the input-line "1 0 1 2 0 0". The maximum total number of marbles will be 20000.
The last line of the input file will be "0 0 0 0 0 0"; do not process this line.
The last line of the input file will be "0 0 0 0 0 0"; do not process this line.
Output
For each collection, output "Collection #k:", where k is the number of the test case, and then either "Can be divided." or "Can't be divided.".
Output a blank line after each test case.
Output a blank line after each test case.
Sample Input
1 0 1 2 0 0 1 0 0 0 1 1 0 0 0 0 0 0
Sample Output
Collection #1:Can't be divided.Collection #2:Can be divided.
#include <iostream>#include <stdio.h>#include <string.h>using namespace std;const int AX = 500000+666;int dp[AX];int a[1000];int main(){int kk = 0;int x;int sum;while(1){sum = 0;int ans = 0;for(int i=1;i<=6;i++){scanf("%d",&x);sum += x*i; int k = 1; //二进制优化while(k<=x){ a[++ans] = k*i;x -= k;k*=2;}if(x) a[++ans] = x*i;}if(sum == 0){break;}printf("Collection #%d:\n",++kk);if(sum%2 == 1){printf("Can't be divided.\n\n");continue;}memset(dp,0,sizeof(dp));dp[0] = 1; //本题0的方案一定存在for(int i=1;i<=ans;i++){for(int j=sum;j>=a[i];j--){if(dp[j-a[i]]){dp[j] = 1;}}}if(dp[sum/2]){printf("Can be divided.\n\n");}else{printf("Can't be divided.\n\n");}}return 0;}
阅读全文
1 0
- 多重背包问题
- 多重背包问题
- 多重背包问题
- 多重背包问题
- P03: 多重背包问题
- 多重背包问题、、、
- P03: 多重背包问题
- 03多重背包问题
- 多重背包问题
- P03: 多重背包问题
- 多重背包问题
- P03: 多重背包问题
- 多重背包问题
- HDU2191多重背包问题
- POJ1014 多重背包问题
- poj2392 多重背包问题
- 多重背包问题
- 多重背包问题
- 【android】点击事件穿透解决方案
- CNN初探(五)------Rich feature hierarchies for accurate object detection and semantic segmentation
- Find Palindrome(dp 金马五校赛-东华大学)
- 调用DLL函数,出现错误 Run-Time Check Failure #0
- Git下载及安装环境配置
- 多重背包问题
- AI黑科技来袭 2017北京硅谷高创会携PanguVR一窥智慧未来
- 谈谈java的运行机制
- Red packet NBUT
- 关于6.828实验中的bootloader链接地址与加载地址的思考
- 基于Swift的iOS应用程序开发:使用表格显示并控制数据(二):删除表格中的数据
- GPU编程
- 【转载】图解WebGL&Three.js工作原理
- python科学计算_numpy_函数库