poj 2754/1014 多重背包之二进制优化
来源:互联网 发布:淘宝内容营销都有哪些 编辑:程序博客网 时间:2024/06/06 19:42
2754题意:给定M(1<=M<=200)以及长度为M的四个数组,分别记为Pairs、Multi、Low、Up,你需要构造一个长度为M的数组Table(其中Low[i]<=Table[i]<=Up[i]),满足∑Multi[i]*Table[i] = 0,且使得∑Pairs[i]*Table[i]尽量大。输入满足至少有一个解。
思路:如果直接上dp,那么复杂度最大可达M*极差*50。其中M是序列长度,50是因为每个数最多有50个取值的可能,极差是∑Multi[i]*Table[i]能达到的最大值和最小值之间的差值。无法承受。下面考虑将其转化为多重背包问题。
将下界单独拿出来作为一部分进行计算,因此[Low[i],Up[i]]就转化为[0, U[i]-L[i]]的一个多重背包。M[i]和P[i]均进行单独的下界计算。计算出 T = L[1]*M[1]+L[2]*M[2].... 之后, 就是一个关于容量T刚好放满的多重背包。
多重背包有一个二进制优化,参见(http://www.cnblogs.com/favourmeng/archive/2012/09/07/2675580.html)。
#include <cstdio>#include <algorithm>#include <cstdlib>#define N 205#define ORI 50000#define INF 0x7fffffffusing namespace std;int dp[200005];int n,m;int up[N],low[N],p[N],w[N];int main(){ while(scanf("%d",&n) != EOF){ m = 0; int presum = 0; for(int i = 0;i<n;i++){ scanf("%d %d %d %d",&p[i],&w[i],&low[i],&up[i]); m += w[i]*low[i]; presum += p[i]*low[i]; up[i] -= low[i]; } m = -m; for(int i = 1;i<=m;i++) dp[i] = -INF; dp[0] = 0; for(int i = 0;i<n;i++){ int num = 1; while(up[i] > num){ for(int j = m;j>=num*w[i];j--) dp[j] = max(dp[j], dp[j-num*w[i]]+num*p[i]); up[i] -= num; num <<= 1; } for(int j = m;j>=up[i]*w[i];j--) dp[j] = max(dp[j], dp[j-w[i]*up[i]]+p[i]*up[i]); } printf("%d\n",dp[m]+presum); } return 0;}
1014题意:有六种石头,分别价值1~6,现在给出价值分别为1~6的石头的数量(石头总数不超过20000)。问能否把这些石头分成两类,使得每类的价值总和相等。
思路:首先求价值总和,如果是奇数必然不能。否则就变成了一个多重背包问题,看看能否凑成总和的一半,用二进制优化。
#include <cstdio>#include <cstring>#include <string>#include <cstdlib>#include <vector>#include <queue>#include <algorithm>#include <cmath>#include <map>#include <set>#include <iostream>#define N 120005#define INF 0x3fffffffint s[7],c = 1;bool dp[N>>1];using namespace std;int main(){ while(1){ int m = 0; for(int i = 1;i<=6;i++){ scanf("%d",&s[i]); m += i*s[i]; } if(m == 0) break; if(m & 1) printf("Collection #%d:\nCan't be divided.\n\n",c++); else{ memset(dp,false,sizeof(dp)); dp[0] = true; m >>= 1; for(int i = 1;i<=6;i++){ if(!s[i]) continue; int num = 1; while(s[i] > num){ for(int j = m;j-num*i>=0;--j) dp[j] |= dp[j - num*i]; s[i] -= num; num <<= 1; } for(int j = m; j - s[i]*i>=0; --j) dp[j] |= dp[j - s[i]*i]; } if(dp[m]) printf("Collection #%d:\nCan be divided.\n\n",c++); else printf("Collection #%d:\nCan't be divided.\n\n",c++); } } return 0;}
0 0
- poj 2754/1014 多重背包之二进制优化
- POJ 1014 Dividing 【DP 之 多重背包 / 二进制优化】
- poj-1014-多重背包+二进制优化
- POJ 1014 Dividing(二进制优化+多重背包)
- POJ 1014 Dividing(多重背包 + 二进制优化 + 01背包)
- POJ 1014 Dividng 多重背包的二进制优化
- 多重背包二进制优化
- 多重背包二进制优化
- 多重背包二进制优化
- 多重背包--二进制优化
- poj 1276 多重背包+二进制优化+单调队列优化
- poj 1014 Dividing 多重背包 二进制拆分
- poj 1014 Dividing(组合数学方法优化/多重背包问题+二进制优化)
- POJ 1276 Cash Machine 多重背包+二进制优化
- poj 1276 Cash Machine(多重背包+二进制优化)
- POJ 1276 二进制优化的多重背包问题
- POJ 1276 Cash Machine 多重背包--二进制优化
- POJ 1276 Cash Machine 【多重背包-二进制优化】
- 【Spring学习09】依赖配置:配置集合
- 使用jQuery——Ajax请求本地json文件
- asd
- smarty模板重要知识点总结
- 文章标题3
- poj 2754/1014 多重背包之二进制优化
- Spring循环依赖
- jsp页面中<%%>中java代码的编译问题
- 2月,English
- 3月30日C++面试题总结
- 文章标题4
- Java线程中sleep()、wait()和notify()和notifyAll()、suspend和resume()、yield()、join()、interrupt()的用法和区别
- 蓝桥杯 基础练习 数列排序
- DOS命令大全