动态规划—币值最大化问题&&找零问题

第一天先看些简单的例子:参考书籍:算法设计与分析基础第三版

例1 《币值最大化问题》

题目:给定一排n个硬币,其面值均为正整数c1,c2,...,cn,这些整数并不一定两两不同。请问如何选择硬币,使得在其原始位置互不相邻的条件下,所选硬币的总金额最大。

分析:

  1.最大金额用F(n)表示,然后找到F(n)的递推关系,我们可以分成两组:一组是包含最后一个硬币的,另一组是不包含最后一个硬币的。

  2.那第一组:F(n) = cn+F(n-2);

      第二组:F(n) = F(n-1);

  即     F(n)=max{cn+F(n-2),F(n-1)},n>1

  3.再结合初始条件:F(0)=0(下标从1开始)0,F(1)=c1

代码:

 

public class demo_1 {
static int[] c = new int[10];
static int[] f = new int[10];
static Scanner in = new Scanner(System.in);
public static void main(String[] args) {
int n = in.nextInt();
for (int i = 1; i <= n; i++) {
c[i] = in.nextInt();
}
System.out.println(coinRow(n));
}

private static int coinRow(int n) {
f[0] = 0;
f[1] = c[1];
for (int i = 2; i <= n; i++) {
f[i] = Math.max(c[i] + f[i-2], f[i-1]);
}
return f[n];
}
}

测试数据:

  我们假设一排硬币是   5,1,2,10,6,2 。最大金额为17

 

例2 《找零问题》

题目:需找零金额为n,最少要用多少面值为d1<d2<…<dm的硬币?(m种面值的各种硬币,d1=1,数量无限)

分析:

  1.设F(n)是在总金额为n的条件下,使用最少硬币的数量

  2.易知F(0) = 0,F(1) = 1;

  3.得到n的途径为 n-dj,然后加上一个面值为dj的硬币,因此 F(n) = min{F(n-dj)} + 1

代码:

public class demo_1 {
static int[] c = new int[10];
static int[] f = new int[10];
static int sum; //总金额
static Scanner in = new Scanner(System.in);
public static void main(String[] args) {
sum = in.nextInt();
int n = in.nextInt(); //硬币种类
c[1] = 1;
for (int i = 2; i <= n; i++) {
c[i] = in.nextInt();
}
System.out.println(changeMaking(n));
}

private static int changeMaking(int n) {
for (int i = 1; i <= sum; i++) {
int temp = 99999999;
int j = 1;
while (j <= n && i >= c[j]) {
temp = Math.min(f[i-c[j]], temp);
j++;
}
f[i] = temp +1;
}
return f[sum];
}
}

测试:sum = 6, n=3,币值分别为1,3,4  F6)= 2

例3《硬币收集问题》下篇介绍

转载于:https://www.cnblogs.com/apex-wzw/p/10774580.html

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值