poj 1742 Coins dp 多重背包 优化
2015-11-07 19:02
399 查看
题目
题目链接:http://poj.org/problem?id=1742题目来源:《挑战》练习题,楼天城男人八题。
简要题意:nn种硬币,第ii种有CiC_i个,每个价值AiA_i问[1,m][1,m]有多少值能被取到。
数据范围:1⩽n⩽100;m⩽105;1⩽Ai⩽105;1⩽Ci⩽10001\leqslant n\leqslant 100; \quad
m\leqslant 10^5; \quad
1\leqslant A_i\leqslant 10^5; \quad
1\leqslant C_i\leqslant 1000
题解
中规中矩的多重背包,有两种比较基本的做法。第一种是使用二进制分解+完全背包。
第二种是新开数组记录来记录当前物品使用的情况。
实现
第二种方法的复杂度更低,可以使用优化手段进一步降低。优化到1s左右之后觉得很难再优化了,看到有200ms的记录,只能颤抖了。
二进制分解代码
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <queue> #include <string> #include <vector> #include <set> #include <map> #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define sz(x) ((int)(x).size()) #define fi first #define se second using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;} // head const int N = 105; const int M = 1e5+5; bool dp[M]; int a ; int b ; void completePack(int c, int m) { for (int i = c; i <= m; i++) { dp[i] |= dp[i-c]; } } void zeroOnePack(int c, int m) { for (int i = m; i >= c; i--) { dp[i] |= dp[i-c]; } } int main() { dp[0] = true; int n, m, v, cnt; while (scanf("%d%d", &n, &m) == 2 && n) { for (int i = 0; i < n; i++) scanf("%d", a+i); for (int i = 0; i < n; i++) scanf("%d", b+i); for (int i = 0; i < n; i++) { v = a[i], cnt = b[i]; if (v*cnt >= m) { completePack(v, m); } else { for (int j = 1; j < cnt; cnt -= j, j <<= 1) { zeroOnePack(j*v, m); } zeroOnePack(cnt*v, m); } } int ans = 0; for (int i = 1; i <= m; i++) { ans += dp[i]; dp[i] = false; } printf("%d\n", ans); } return 0; }
模剩余优化
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <queue> #include <string> #include <vector> #include <set> #include <map> #include <bitset> #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define sz(x) ((int)(x).size()) #define fi first #define se second using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;} // head const int N = 105; const int M = 1e5+5; int a ; int b ; int cnt[M]; int use[M]; bool dp[M]; int main() { dp[0] = true; int n, m; while (scanf("%d%d", &n, &m) == 2 && n) { for (int i = 0; i < n; i++) scanf("%d", a+i); for (int i = 0; i < n; i++) scanf("%d", b+i); int ans = 0, from; for (int i = 0; i < n; i++) { for (int j = a[i]; j <= m; j++) { if (!dp[j] && dp[from = j-a[i]] && (use[from] != a[i] || cnt[from] < b[i])) { dp[j] = true; cnt[j] = use[from] != a[i] ? 1 : cnt[from]+1; use[j] = a[i]; ans++; } } } printf("%d\n", ans); for (int i = 1; i <= m; i++) { dp[i] = use[i] = cnt[i] = 0; } } return 0; }
相关文章推荐
- init rtl8367
- 《软件需求最佳实践》阅读笔记一
- 卜算子·谒杜甫草堂
- 代理模式
- 字符串操作函数、数学函数
- 三种方式实现自定义圆形进度条ProgressBar
- HDU 5522 Numbers
- 利用粒子群算法求解非线性二层规划问题(matlab)
- python机器学习《入门》
- 图片轮播
- hdu5533Dancing Stars on Me
- 机器学习实战--KNN 算法 笔记
- java多线程细节归纳汇总
- Linux学习笔记
- jQuery-1.9.1源码分析系列(三) Sizzle选择器引擎——编译原理续(伪类分割器setMatcher)
- 第五次团队作业
- 51单片机英文引脚等中文对照
- 51单片机英文引脚等中文对照
- 如何判断socket是否连接,异常断开拔出网线
- Java中的final理解