博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[POJ 1742] Coins 【DP】
阅读量:5127 次
发布时间:2019-06-13

本文共 1201 字,大约阅读时间需要 4 分钟。

题目链接:

 

题目大意

现有 n 种不同的硬币,每种的面值为 Vi ,数量为 Ni ,问使用这些硬币共能凑出 [1,m] 范围内的多少种面值。

 

题目分析

使用一种 O(nm) 的 DP (据说这是类多重背包?),枚举每一种硬币,对于每一种硬币 i 枚举每一个面值 j ,如果这个面值 j 使用前 i-1 种硬币已经可以凑出,就直接跳过,否则尝试加入一个硬币 i ,看是否能凑出 j 。需要满足 (f[j - Vi] == true) && (UseNum[j - Vi] + 1 <= Ni) ,这样就可以了。对于每一个 i ,枚举 j 之前将 UseNum 数组清零。

 

代码

#include 
#include
#include
#include
#include
#include
using namespace std;const int MaxN = 100 + 5, MaxM = 100000 + 5;int n, m, Ans;int V[MaxN], Num[MaxN], UseNum[MaxM];bool f[MaxM];int main(){ while (true) { scanf("%d%d", &n, &m); if (n == 0 && m == 0) break; for (int i = 1; i <= n; ++i) scanf("%d", &V[i]); for (int i = 1; i <= n; ++i) scanf("%d", &Num[i]); Ans = 0; for (int i = 1; i <= m; ++i) f[i] = false; f[0] = true; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) UseNum[j] = 0; for (int j = V[i]; j <= m; ++j) { if (f[j]) continue; if (f[j - V[i]] && UseNum[j - V[i]] + 1 <= Num[i]) { f[j] = true; UseNum[j] = UseNum[j - V[i]] + 1; } } } for (int i = 1; i <= m; ++i) if (f[i]) ++Ans; printf("%d\n", Ans); } return 0;}

  

转载于:https://www.cnblogs.com/JoeFan/p/4165769.html

你可能感兴趣的文章
PHP - 判断php是否对表单数据内的特殊字符自动转义
查看>>
简易商城 [ html + css ] 练习
查看>>
Linux 下Makefile教程
查看>>
[转]MSP430另一种UART实现
查看>>
myeclipse部署多个web工程
查看>>
tcp_协议基础
查看>>
layui弹窗 之 iframe关闭
查看>>
【BZOJ2565】最长双回文串 Manacher
查看>>
There is no PasswordEncoder mapped for the id "null"
查看>>
windows10 conda python多版本切换
查看>>
Linux配置日志服务器
查看>>
P6 EPPM 16.1 安装和配置指南 1
查看>>
C语言:九九乘法表打印
查看>>
Java_Activiti5_菜鸟也来学Activiti5工作流_之JUnit单元测试(四)
查看>>
codeforce626D (概率)
查看>>
HD1385Minimum Transport Cost(Floyd + 输出路径)
查看>>
Ajax技术
查看>>
MVC解决方案发布IIS 登录页面需要输入两次帐号问题
查看>>
Visual Studio 2017 初次体验
查看>>
zTree树
查看>>