POJ
来源:互联网 发布:iphone7专业拍照软件 编辑:程序博客网 时间:2024/06/01 21:15
传送门:POJ 1742
题意:有n中面额的钱,每种有ci个,问1--m里有多少个数能用这些钱组成。
思路:一看就知道是多重背包,不过是重量等于价值的特殊形态而已,并且数据量明显不能直接暴力,这里有两种优化方法,一是二进制优化,不过这里dp要换成bool数组表示能否组成的状态,要按普通背包写的话可能会t。
二是单调队列优化,这个题普通的单调队列优化也是过不了的,在单调队列的基础上还要特判出01背包和完全背包,并且运用单调队列的部分也要相应变形,由于我们只需要表示能否组成的状态就好了,因此我们可以用一个sum表示队列中的元素和,这样可以减少入队出队操作。
二进制优化代码:
#include<iostream>#include<stdio.h>#include<algorithm>#include<string.h>using namespace std;typedef pair<int,int>P;const int MAXN=100010;int gcd(int a,int b){return b?gcd(b,a%b):a;}bool dp[MAXN];int V;P p[MAXN];void zero(int cost){ for(int i=V;i>=cost;i--) dp[i] |= dp[i-cost];} void complet(int cost) { for(int i=cost;i<=V;i++) dp[i] |= dp[i-cost]; } void multi(int cost, int amount) { if(cost*amount>=V) { complet(cost); return; } int k=1; while(k<amount) { zero(k*cost); amount-=k; k=k*2; } zero(amount*cost);} //多重背包的二进制优化 V-背包总容量 cost-单件物品花费(重量) amount-单件物品数量 weight-单件物品价值 int main(){int n, m;while(scanf("%d %d", &n, &m), n + m){V = m;memset(dp, 0, sizeof(dp));for(int i = 0; i < n; i++)scanf("%d", &p[i].first);for(int i = 0; i < n; i++)scanf("%d", &p[i].second);//sort(p, p + n);dp[0] = 1;for(int i = 0; i < n; i++){multi(p[i].first, p[i].second);}int ans = 0;for(int i = 1; i <= m; i++){ans += dp[i];}printf("%d\n", ans);} return 0;}
单调队列优化代码戳这里。
阅读全文
0 0
- POJ
- poj
- POJ
- POJ
- poj
- poj
- POJ
- POJ
- poj
- POJ
- POJ
- POJ
- POJ
- POJ
- POJ
- POJ
- POJ
- POJ
- Ubuntu16.04 + Windows10 双系统 开机默认项改为windows启动
- Cohort analysis
- linux-screen
- 数据结构和算法 —— 绪论
- spring mvc 配置web.xml时“/”和“/*”的区别
- POJ
- ArrayDeque
- sch find similar objects
- Java新增的Predicate操作集合
- hdu 1338 Game Prediction
- 循环双链表--JAVA
- No CurrentSessionContext configured!
- MongoDB集群实战攻略
- A