题意 : 有 n 种面额的硬币,给出各种面额硬币的数量和和面额数,求最多能搭配出几种不超过 m 的金额?

分析 :

这题可用多重背包来解,但这里不讨论这种做法。

如果之前有接触过背包DP的可以自然想到DP数组的定义 ==> dp[i][j] 表示使用前 i 种硬币是否可以凑成面额 j 。

根据这样的定义,则一开始初始化 dp[0][0] = true 最后统计 dp[n][1 ~ m] 为 true 的数量即为答案

状态转移方程为 dp[i][j] |= dp[i-1][ j - k*val[i] ] ( k 表示取 k 个第 i 种硬币、val[i] 表示第 i 种硬币的面额 )

转移方程的意义不难理解,需要考虑当前的 dp[i][j] 可以从哪些状态转移而来,如下

使用第 i 种硬币刚好凑成 j 的值应当为上个状态( dp[i-1][] )合法的 j-val[i]、j-2*val[i]、j-3*val[i]....

故代码应当为一个如下所示的三重循环,但是复杂度较高无法通过这题.....

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn = 111;bool dp[maxn][100005];
int num[maxn], val[maxn];int main(void)
{int N, C;while(~scanf("%d %d", &N, &C) && !(N==0 && C==0)){for(int i=1; i<=N; i++) scanf("%d", &val[i]);for(int i=1; i<=N; i++) scanf("%d", &num[i]);memset(dp, false, sizeof(dp));dp[0][0] = true;for(int i=1; i<=N; i++){for(int j=0; j<=C; j++){for(int k=0; k<=num[i] && k*val[i]<=j; k++){dp[i][j] |= dp[i-1][j-k*val[i]];}}}printf("%d\n", count(dp[N]+1, dp[N]+C+1, true));}return 0;
}

View Code

通常使用 dp 数组只记录布尔值是种浪费的做法,一般就去考虑在保证正确性的情况下改变 dp 含义记录更多信息去降低复杂度!

现将 dp 含义改变为 ==> dp[i][j] 表示用前 i 种硬币凑成 j 时第 i 种硬币最多还可以剩多少

挑战书上是直接给出了定义,但是我更乐于探寻这玩意是什么来的? 注:以下都是我自己的想法

想想上面的解法,好像会发现其实如果我当前考虑过 dp[i][j] = true 了,那么 dp[i][j+val[i]]、dp[i][j+2*val[i]]、dp[i][j+3*val[i]]... 应该都为 true

而枚举 j 的顺序也恰好是从小到大,所以必定会枚举到 dp[i][j+val[i]]、dp[i][j+2*val[i]]...,所以何不写成如下这样

for(int i=1; i<=N; i++){for(int j=0; j<=C; j++){dp[j] |= dp[j-val[i]];}
}

运行了样例之后发现这样的做法得出的答案比标准答案更大!为什么?因为这样的做法没有考虑到数量,一种硬币的数量是有限的

所以当 j+k*val[i] 的 k 超过了规定数量的时候就会发生错误,使得一些本该为 false 的 dp 数组值变成了 true,所以我们需要记录数量!

复杂度为 O(n*m) 在 POJ 上跑了 2016MS

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn = 111;int dp[100005];
int num[maxn], val[maxn];bool fun(int x)
{ if(x>=0) return true; return false; }int main(void)
{int N, C;while(~scanf("%d %d", &N, &C) && !(N==0 && C==0)){for(int i=1; i<=N; i++) scanf("%d", &val[i]);for(int i=1; i<=N; i++) scanf("%d", &num[i]);memset(dp, -1, sizeof(dp));dp[0] = 0;for(int i=1; i<=N; i++){for(int j=0; j<=C; j++){if(dp[j] >= 0) dp[j] = num[i];else if(j < val[i] || dp[j-val[i]] <= 0) dp[j] = -1;else dp[j] = dp[j-val[i]] - 1;}}printf("%d\n", count_if(dp+1, dp+1+C, fun));}return 0;
}

View Code

转载于:https://www.cnblogs.com/LiHior/p/8053149.html

POJ 1742 Coins ( 经典多重部分和问题 DP || 多重背包 )相关推荐

  1. [POJ 1742] Coins 【DP】

    题目链接:POJ - 1742 题目大意 现有 n 种不同的硬币,每种的面值为 Vi ,数量为 Ni ,问使用这些硬币共能凑出 [1,m] 范围内的多少种面值. 题目分析 使用一种 O(nm) 的 D ...

  2. POJ 1742 Coins

    题目链接 题意 给出N个硬币和数量,求一共可以组合成几种情况 AC bitset 用二进制的下标表示和,最后1的个数表示种类数 优化:用二次方移动加快速度 例如: 移动7次(需要4次) 1.0000 ...

  3. C - BLG POJ - 1417 种类并查集加dp(背包)

    思路:刚看这道题感觉什么都不清楚,人物之间的关系一点也看不出来,都不知道怎么写,连并查集都没看出来,但是你可以仔细分析一下,当输入字符串为"yes"的时候,我们设输入的值为x和y, ...

  4. hdu 1171 dp(多重背包)

    View Code //hdu 1171 dp(多重背包)//题意:把所有物品的价值尽量分为相等的两份,不能等分的话 //后面那份可以稍小于前面的 //求出价值总和后,令价值的一半为背包容量,让背包尽 ...

  5. poj 3728 The merchant// lca(倍增实现) + dp || tarjan+并查集路径上dp

    poj 3728 The merchant// lca(倍增实现) + dp Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: ...

  6. bzoj2287【POJ Challenge】消失之物 缺一01背包

    bzoj2287[POJ Challenge]消失之物 缺一01背包 链接 bzoj 思路 分治solve(l,r,arr)表示缺少物品\([l,r]\)的dp数组arr. 然后solve(l,mid ...

  7. ZOJ 3450 Doraemon's Railgun (DP·分组背包)

    题意  多啦A梦有一个超电磁炮  然后要打死n堆敌人  在同一条射线上的敌人只有先打死前面的一堆才能打后面的一堆  给你打死某堆敌人需要的时间和这堆敌人的人数   问你在T0时间内最多打死多少个敌人 ...

  8. Coins POJ - 1742(多重背包+是否装满问题)

    题意: 给定n种面值的硬币面值分别为WiW_{i}Wi​个数为CiC_{i}Ci​,问用这些硬币可以组成1~m之间的多少面值. 题目: People in Silverland use coins.T ...

  9. Coins POJ - 1742(题解)

    原题 http://poj.org/problem?id=1742 题目大意 给出硬币面额及每种硬币的个数,求从1到m能凑出面额的个数. 题目分析 多重背包模板题,这里讲一下用一维dp来解这道题.与完 ...

最新文章

  1. Javascript 装饰器极速指南
  2. hdu4966 最小树形图(最少辅导花费)
  3. html 关键帧作标记,关键帧有什么用?
  4. MySQL与oracle报错显示_Oracle中判断表是否存在再删除表避免报错与MySql和SqlServer的不同...
  5. python web cgi
  6. Exchange 企业邮件与Windows安全应用 — Exchange 2007 收件人管理
  7. 图像局部特征(十)--BRIEF描述子
  8. maven安装配置:报错NB: JAVA_HOME should point to a JDK not a JRE
  9. Chrome快捷键整理
  10. WindowsCMD配置代理
  11. MaxIO智能缓存加速技术
  12. 数据库,表数据的插入
  13. MVG读书笔记——相机模型
  14. 一起来设计“塔防游戏”吧
  15. Oracle 数据完整性的实例
  16. 消除Xcode iOS项目的警告
  17. 常见电路分析十一:y型连接和三角形连接
  18. 影响整个世界的十种算法
  19. 将Windbg附加到软件进程上排查异常闪退的问题
  20. pip下载扩展包时报错 ValueError: check_hostname requires server_hostname

热门文章

  1. 几个有趣的python技巧
  2. AI研发工程师成长指南
  3. 做最好的自己——读书笔记
  4. core java 8~9(GUI AWT事件处理机制)
  5. EasyUI 在aspx页面显示高度不正常解决办法
  6. Linux中fork的秘密
  7. b/s c/s结构的区别!
  8. 【REPERTOIRE】Rastaman Vibration
  9. 所谓语音合成 是计算机根据语言学,计算语言学完整1
  10. python考试有什么用_Python有什么用?2020年学习Python的10个理由