POJ1742 Coins(男人八题之一)
前言
大名鼎鼎的男人八题,终于见识了...
题面
http://poj.org/problem?id=1742
分析
§ 1 多重背包
这很显然是一个完全背包问题,考虑转移方程:
DP[i][j]表示用前i种硬币能否取到金额j,ture表示可以,false表示不行。
则有
DP[i][j] = DP[i - 1][j] | DP[i - 1][j - k * Ai], 0 ≤ k ≤ Ci, j - k * Ai ≥ 0
这是一个O(N3)的算法,考虑到数据范围1 ≤ N ≤ 100, M ≤ 100000, 1 ≤ Ci ≤ 1000,显然会超时。
§ 2 优化
考虑上面的转移方程,每个方程只记录了可行解的存在与否;而事实上,当前第i种硬币的剩余数也是一个状态,而此前的方程关于这个状态是靠k来枚举。
我们可以考虑一下完全背包和多重背包的异处,正是多了一个物品数量的限制,才使我们的枚举增加了一个维度,导致时间复杂度增加;而我们同时还要记录当前状态可达到的最大价值(普通多重背包),因而枚举选的物品数量的循环时必不可少的。但是,在这个问题中,我们只需要判断可行解的存在性。因此,我们可以用DP[i][j]来记录用前i种硬币,在取到金额j的情况下,第i种硬币剩余的最大数量。(不能用-1表示)
则有
DP[i][j] =
- C[i], DP[i - 1][j] ≥ 0(如果前(i-1)种硬币已经足以凑出这个金额j,那么就根本用不着第种硬币,因此全部剩下,也就是Ci)
- -1, DP[i][j - A[i]] ≤ 0 || j < A[i](若前面凑更小的面额时已经用尽第i种硬币,或者当前硬币的面额太大了,那么就凑不出来,即-1)
- DP[i][j - A[i]] - 1
注意这些条件时依次判断的。
(如果以上看了仍然不懂的同学,可以去看这个dalao写的详细推理过程 http://www.hankcs.com/program/cpp/poj-1742-coins.html)
因而,时间复杂度就被降到了O(N2)。
还有很重要的一点,之间建N * M的数组是会超空间的,因此,要使用滚动数组。
§ 3 总结
事实上,这题降维就是考的只判断解是否可行的条件。一般来说,这种思路很难想到,很少人会去想写这样一个多重背包的方程,但是,正是这个问题独特的性质,使得它可行。
而且这个问题还有一种用单调队列的写法,目前还没有弄懂,不过也是多重背包的一大利器。
§ 4 参考代码
// POJ1742
// Coins
// LouTiancheng@POJ
#include <cstdio>
#include <cstring>
#include <algorithm>
const int MAXN = ;
const int MAXM = ; int N, M, DP[][MAXM] = {}, A[MAXN], C[MAXN], i, j; void solve(); int main() {
while (scanf("%d%d", &N, &M) == ) {
if (N == || M == ) break;
solve();
}
return ;
} void solve() {
for (i = ; i < N; i++) scanf("%d", &A[i]);
for (i = ; i < N; i++) scanf("%d", &C[i]);
int *prv = DP[], *nxt = DP[];
memset(prv + , -, sizeof(int) * M);
prv[] = ;
for (i = ; i < N; i++) {
for (j = ; j <= M; j++)
if (prv[j] >= ) nxt[j] = C[i];
else if (j < A[i] || nxt[j - A[i]] <= ) nxt[j] = -;
else nxt[j] = nxt[j - A[i]] - ;
std::swap(prv, nxt);
}
int ans = ;
for (i = ; i <= M; i++)
if (prv[i] >= ) ans++;
printf("%d\n", ans);
}
另外,有问题的童鞋欢迎提问~
谢谢大家!
POJ1742 Coins(男人八题之一)的更多相关文章
- poj 1737男人八题之一 orz ltc
这是楼教主的男人八题之一.很高兴我能做八分之一的男人了. 题目大意:求有n个顶点的连通图有多少个. 解法: 1. 用总数减去不联通的图(网上说可以,我觉得时间悬) 2. 用动态规划(数学递推) ...
- poj 1741 楼教主男人八题之中的一个:树分治
http://poj.org/problem? id=1741 Description Give a tree with n vertices,each edge has a length(posit ...
- Cogs 1714. [POJ1741][男人八题]树上的点对(点分治)
[POJ1741][男人八题]树上的点对 ★★★ 输入文件:poj1741_tree.in 输出文件:poj1741_tree.out 简单对比 时间限制:1 s 内存限制:256 MB [题目描述] ...
- 新男人八题---AStringGame
终于完成进度男人1/8,为了这题学了sam= = 题意先有一个串,n个子串,两个人轮流每次在子串上加字符,要求加完后还是原串的子串,最后不能加的就是输者,求赢的人 解法:sam之后在构造的状态图上跑s ...
- poj 1742(好题,楼天城男人八题,混合背包)
Coins Time Limit: 3000MS Memory Limit: 30000K Total Submissions: 33269 Accepted: 11295 Descripti ...
- 博弈论(男人八题):POJ 1740 A New Stone Game
A New Stone Game Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 5694 Accepted: 3119 ...
- poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 14874 Accepted: 5118 De ...
- nyoj137 取石子(三) 楼教主男人八题之一
思路:一堆时,N态.两堆时,当两堆数量相同,P态,不同为N态.三堆时,先手可以变成两堆一样的,必胜N态. 此时可以总结规律:堆数为偶数可能且石子数都是两两相同的,为P态.分析四堆时,当四堆中两两数量一 ...
- 《学习OpenCV》练习题第四章第八题ab
这道题是利用OpenCV例子程序里自带的人脸检测程序,做点图像的复制操作以及alpha融合. 说明:人脸检测的程序我参照了网上现有的例子程序,没有用我用的OpenCV版本(2.4.5)的facedet ...
随机推荐
- AVL树和伸展树 -数据结构(C语言实现)
读数据结构与算法分析 AVL树 带有平衡条件的二叉树,通常要求每颗树的左右子树深度差<=1 可以将破坏平衡的插入操作分为四种,最后通过旋转恢复平衡 破坏平衡的插入方式 描述 恢复平衡旋转方式 L ...
- NodeJs学习笔记01-你好Node
如果你对NodeJs略知一二,不禁会感叹,使用JS的语法和代码习惯就能开发一个网站的后台,实现复杂的数据交互,牛! 对于学习java和php就夹生的小码农来说,简直就是靡靡之音呐~~~ 今晚带着忐忑的 ...
- Ubuntu—终端下重启与关机
重启命令 : 1.shutdown -r now 立刻重启 2.shutdown -r 10 过10分钟自动重启 3.shutdown -r 20:35 在时间为20:35 ...
- [Data Structures and Algorithms - 1] Introduction & Mathematics
References: 1. Stanford University CS97SI by Jaehyun Park 2. Introduction to Algorithms 3. Kuangbin' ...
- 十一:Centralized Cache Management in HDFS 集中缓存管理
集中的HDFS缓存管理,该机制可以让用户缓存特定的hdfs路径,这些块缓存在堆外内存中.namenode指导datanode完成这个工作. Centralized cache management i ...
- Thunder团队第六周 - Scrum会7
Scrum会议7 小组名称:Thunder 项目名称:i阅app Scrum Master:杨梓瑞 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传 ...
- Scrum1
Scrum1 组员 任务分工 贡献 林泽宇 团队分工.撰写博客.修改完善需求规格说明书.整理代码规范 李涵 后端架构设计 尹海川 logo设计修改.数据库数据 郏敏杰 课堂展示.查阅资料.整理关键和难 ...
- Java 集合框架之Collection
此图是 java 中 Collection 相关的接口与类的关系的类图.其中,类只是集合框架的一部分,比较常用的一部分. 第一次画类图,着实很费劲,不过收获也不小. 下面是相关接口和类的解释说明.文字 ...
- oracle数据库之游标的使用
一.游标概念 为了处理 SQL 语句,ORACLE 必须分配一片叫上下文( context area )的区域来处理所必需的信息,其中包括要处理的行的数目,一个指向语句被分析以后的表示形式的指针以及查 ...
- osg::Vec2 Vec3 Vec4
osg::Vec2可以用于保存2D纹理坐标. osg::Vec3是一个三维浮点数数组. osg::Vec4用于保存颜色数据.