文章目录

  • Leecode 322零钱兑换
  • Leecode 518零钱兑换II

Leecode 322零钱兑换

题目大意
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。你可以认为每种硬币的数量是无限的。
题解思路
状态确定:dp[i]表示凑成面值i所需要的最小硬币数。从0开始遍历一直到amount,求出dp[amount]即为所求解。
状态方程:
dp[i]=min(dp[i-coins[j],dp[i]),i>=coins[i]
技巧:初始时给所有的dp[i]赋值为amount+1,最多硬币数是小于这个值的,如果遍历到amount,其值dp[amount]仍为amount+1,说明没有任何一种硬币组合数使其面值等于amount,则返回-1;在这个初始赋值为最大值时,所有
边界确定:dp[0]=0;
参考代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int coinChange(int* coins, int coinsSize, int amount){int dp[amount+1];
for(int i=0;i<=amount;i++){dp[i]=amount+1;//便于后序检测是否有面值无法用该硬币组合数构成
}
dp[0]=0;
for(int i=1;i<=amount;i++){for(int j=0;j<coinsSize;j++){if(i>=coins[j])//如果当前待求面值大于或等于该硬币的值,即一定不能选该枚硬币,否则可选dp[i]=min(dp[i],dp[i-coins[j]]+1);}
}if(dp[amount]>amount)return -1;
else return dp[amount];
}
int main(){int n;int coins[12],amount;cin>>n;for(int i=0;i<n;i++){cin>>coins[i];}cin>>amount;cout<<coinChange(coins,n,amount); return 0;
}

题目复盘
刚开始看到这道题目时就模仿着之前做的题目往二维套,写了下面这个思虑不周的错误代码


//  int dp[13][10001]={0};
//  for(int j=1;j<=amount;j++)
//      dp[0][j]=-1;
//  dp[1][1]=1;
//  for(int i=1;i<=coinsSize;i++){//      for(int j=0;j<=amount;j++)
//      if(j<coins[i-1]&&dp[i-1][j]!=-1)
//          dp[i][j]=dp[i-1][j];
//      else if(dp[i-1][j]==-1)
//          dp[i][j]=-1;
//      else if(coins[i-1]<j)
//          dp[i][j]=min(dp[i-1][j],dp[i-1][j-coins[i-1]]+1);
//  }
//  return dp[coinsSize+1][amount];

该代码错误如下:
向之前那样一次遍历前i个硬币,这种默认硬币是只能使用一次,实际每个硬币可使用多次
之后看了题解用一位数组存储状态,因为初值赋的不合理,使后面思路凌乱,又写了以下错误代码:

 //一维动态规划
//  int dp[10000]={0};
//  //for(int i=0;i<coinsSize;i++) dp[coins[i]]=1;
//  for(int i=1;i<=amount;i++)
//      {//
//          int mi=10000;
//          for(int j=0;j<coinsSize;j++)
//            {//              if(i==coins[j]){//                  dp[i]=1;
//                  break;
//              }
//                if(i>coins[j])
//               dp[i]=fmin(dp[i-coins[j]]+1,dp[i]);
                else if(i<coins[j])
                 dp[i]=fmin(dp[i],dp[i]);
//            }
//
//            if(mi=-1)
//                dp[i]=-1;
//            else
//          dp[i]=mi+1;
//      }
//  return dp[amount];

希望下次做题时逻辑能更清晰一些,想的更明白一些,灵活运用动态规划这个思想!

Leecode 518零钱兑换II

题意

给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。
请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带符号整数。

解题思路

为了避免金币种类因顺序不同遍历导致的重复,此解题在外层先遍历金币的种类数,在内层遍历构成的金额数。这样构成每一金额的硬币都是按顺序排好的即可避免重复。用dp[i]存放使用前面几种类硬币构成的金额i的方案个数,在遍历到本层时再用dp[i]=dp[i]+dp[i-coins[j]]更新到达本层时构成金额i的种类数。
状态表示:dp[i]凑成金额i的组合数
状态转换: dp[i]=dp[i]+dp[i-coins[j]],i>=coins[j]
源码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int coinChange(int* coins, int coinsSize, int amount){//int dp[amount+1]={0};for(int i=0;i<=amount;i++)dp[i]=0;
//  for(int i=0;i<=amount;i++)
//      dp[i]=amount+1; //给dp[i] 赋初值为一个不可能达到的值,如果最后真的等于这个值说明dp[i]不可能实现 dp[0]=1;
//  for(int i=1;i<=amount;i++){//      for(int j=0;j<coinsSize;j++)//遍历可用的每一个硬币,看是否能使用
//          if(i>=coins[j])
//              dp[i]+=dp[i-coins[j]];
//  }for(int i=0;i<coinsSize;i++){//遍历可用的每一个硬币,看是否能使用for(int j=0;j<=amount;j++)if(j>=coins[i])dp[j]+=dp[j-coins[i]];}return dp[amount];
}
int main(){int n;int coins[12],amount;cin>>n;for(int i=0;i<n;i++){cin>>coins[i];}cin>>amount;cout<<coinChange(coins,n,amount); return 0;
}

复盘
刚开始认为这道题与322除了dp[i]含义不同与状态方程不同没什么区别,直到手动运行上述注释的错误代码后发现那种写法有重复的方案。如coins[1 2 5],amount=5;在刚开始写的时候方案:“1 2 2”和方案“ 2 2 1”是都被记入到dp[i]中的,导致了很多重复。真佩服那种第一次就能想到避免重复的方法的人!

完全背包问题Leecode322零钱兑换和Leecode518零钱兑换||相关推荐

  1. 深入解析之将100元兑换为1元、5元、10元的零钱,请问有多少种兑换方法

    要将100元兑换为1元.5元.10元的零钱,请问有多少种兑换方法?这道算法题不知不觉走进了我的世界,引起了我极大的兴趣.现在就将我对它的研究分享出来,供大家点评. 看到这个题目的第一感觉就是一个三元一 ...

  2. 将100元兑换为1元、5元、10元的零钱,请问有多少种兑换方法?

    public static void main(String[] args) {//将100元兑换为1元.5元.10元的零钱,请问有多少种兑换方法?//i为一元数量,j为五元数量,k为十元数量int ...

  3. 【必备算法】动态规划:LeetCode题(六)322. 零钱兑换,518. 零钱兑换 II

    322. 零钱兑换² 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 示例 1: ...

  4. python换零钱_Python算法之零钱兑换问题的解法

    比如:顾客购物买37元东西,给了100元,要找63元,那最少数量就是1张50元,1张10元,3张1元,一共4张. 方法一: 贪心策略 解决这个问题,最直观的就是使用贪心策略.我们会从最大面值的钱开始, ...

  5. python找零钱_Python递归 - 找零钱

    特殊的方法-循环: #无法解决某些情况,例如存在21元的零钱 def fun(n): count = 0 while n > 25: n = n - 25 count = count + 1 w ...

  6. cms小猪o2o企业付款配置中微信提现配置实现商家转账到零钱(企业付款到零钱)解决:“操作失败!产品权限验证失败,请查看您当前是否具有该产品的权限“的错误提示

    先说下概念什么是商家转账到零钱?其实这个功能是由企业付款到零钱功能演变过来的,微信支付里面在2022年5月之前这个功能一直叫"企业付款到零钱"后来因为业务需求改成了"商家 ...

  7. php企业微信付款到零钱,企业付款到零钱功能介绍及常见问题

    Q:为什么我在[产品中心]找不到[企业付款到零钱]产品? A:需同时满足三个条件,才能看到开通入口: 1)入驻满足90天: 2)截止今日往回推30天有连续不间断的交易: 3)交易需为正常的健康交易. ...

  8. 凑零钱问题_凑零钱的组合

    给定K种面值c1,c2,....ck,每种金币数量,例举总和为amount的,至少需要的金币的组合 关于计算金币数量有解法,金币组合方式可以参考,暴力解,从小到大,找到即是最小组合 import ja ...

  9. html网页代码实现找零钱,算法训练 找零钱

    资源限制 时间限制:1.0s   内存限制:256.0MB 问题描述 有n个人正在饭堂排队买海北鸡饭.每份海北鸡饭要25元.奇怪的是,每个人手里只有一张钞票(每张钞票的面值为25.50.100元),而 ...

最新文章

  1. Spring_boot_pom.xml和启动方式
  2. 无法连接NVIDIA驱动:NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver
  3. [leetcode] 数字游戏
  4. jquery自动补全
  5. c语言#include后的尖括号和双引号有什么区别?
  6. php服务器队列执行,lnmp php添加队列服务器的配置
  7. Yii 框架里数据库操作详解-[增加、查询、更新、删除的方法](转)
  8. js 浅拷贝直接赋值_JS中的赋值、浅拷贝与深拷贝
  9. 一种真正意义上的Session劫持
  10. 诺基亚首款5G手机正式发布!还有Nokia 5310经典再现
  11. Linux查看文件内容的6种命令
  12. Bluno 是干什么的?- 云物联戒烟设备的可选原型之一
  13. Python小程序(3)--BMR(基础代谢率)计算器
  14. 10种软件开发模型整理
  15. windows10一键修改开机动画
  16. 哔哩哔哩视频下载助手
  17. netty 高匿ip检测_检测代理IP匿名程度的方法
  18. elipse配色方案
  19. Python课程总结
  20. 计算机系统引导失败怎么办,win7系统引导选择失败怎么办|win7系统引导选择失败的解决方法...

热门文章

  1. ASML最后的倔强,不愿失去中国市场,继续供应28纳米光刻机
  2. 不同传输速率的高速数据采集卡的使用方法
  3. 【产品】一次完整的产品需求分析及设计流程分享
  4. 邮件系统日志查看方法
  5. 计算机汽油累计调价公式,2018年油价调整明细_2018年油价调整时间表及历史调价幅度汇总...
  6. 没有恢复出来数据却还要收我的钱,坑!吗?
  7. java实现分布式事务的三种方案
  8. 计算机科学与技术专业学点啥
  9. 冒泡排序zzzzzzz
  10. php中fopen打开mp4边下边播,解决mp4流媒体转换不能边下边播