`

Square Coins一个DP问题分析

阅读更多
问题描述:
People in Silverland use square coins. Not only they have square shapes but also their values are square numbers. Coins with values of all square numbers up to 289 (=172), i.e., 1-credit coins, 4-credit coins, 9-credit coins, ..., and 289-credit coins, are available in Silverland.

There are four combinations of coins to pay ten credits:

ten 1-credit coins,
one 4-credit coin and six 1-credit coins,
two 4-credit coins and two 1-credit coins, and
one 9-credit coin and one 1-credit coin.
Your mission is to count the number of ways to pay a given amount using coins of Silverland.

Input

The input consists of lines each containing an integer meaning an amount to be paid, followed by a line containing a zero. You may assume that all the amounts are positive and less than 300.

Output

For each of the given amount, one line containing a single integer representing the number of combinations of coins should be output. No other characters should appear in the output.

Sample Input

2
10
30
0

Sample Output

1
4
27
问题分析:
这个问题是个典型的动态规划问题,从底往上推就行了。
这个问题的关键是建立递推式:
二维数组w,其中w[i][j]代表使用<=i*i的币值的钱币来付款j元钱的的可能的方法数
这样我们对w[i][j]来构造递推式:
w[i][j] = sum { w[i-1][j-k*i*i] } 其中k=0,1,... j-k*i*i >= 0
这个个含义是使用<=i*i的币值的钱币付j元钱的方法数,就是我用0...k个i*i币值来
替换掉以前用<=(i-1)*(i-1)币值的等额的钱 来付j元钱的方法数。而用i*i替换出等
额钱的方法数,其实就是用<=(i-1)*(i-1)币值的钱来付j-k*i*i的方法数。
理解这个公式也就很容易理解代码了。
cpp 代码
  1. #include<iostream></iostream>   
  2. using namespace std;   
  3.   
  4. int w[18][301];   
  5.   
  6. void NumOfMethod(){   
  7.      int i,j,k;   
  8.     /*初始化w的值,用<=1币值显然有一种方法,j=0初始化为1的原因是,  
  9.       w[i][j] += w[i-1][j-k*i*i],如果j-k*i*i == 0,即用k个币值为  
  10.       i*i的硬币恰好可以替换所有的所有的硬币来支付,这个方法数是1而不是0,  
  11.       这比较特殊,与用<=(i-1)*(i-1)币值的钱来付j-k*i*i的方法数不相等*/  
  12.   
  13.     for(i = 1; i < 18; i++)   
  14.         for(j = 0; j < 301; j++){   
  15.            if(i == 1 || j == 0)   
  16.                w[i][j] = 1;   
  17.            else  
  18.                w[i][j] = 0;   
  19.         }   
  20.     //下面就是从底往上推的一个过程了:   
  21.     for(i = 2; i < 18; i++)   
  22.         for(j = 1; j < 301; j++)   
  23.             for(k = 0; j-k*i*i >= 0; k++)   
  24.                 w[i][j] += w[i-1][j-k*i*i];   
  25.        
  26. }   
  27. int main(){   
  28.     int n;   
  29.     NumOfMethod();   
  30.     while(cin>>n,n){   
  31.       cout << w[17][n] << endl;   
  32.     }   
  33.     return 0;   
  34. }  

 

     当然如果想节省空间可以用两个一维的数组交替使用来替换掉w那个二维数组。

分享到:
评论
1 楼 fuliang 2007-12-17  
初始化w的值,用<=1币值显然有一种方法,j=0初始化为1的原因是,w[i][j] += w[i-1][j-k*i*i],如果j-k*i*i == 0,即用k个币值为i*i的硬币恰好可以替换所有的所有的硬币来支付,这个方法数是1而不是0,这比较特殊,与用<=(i-1)*(i-1)币值的钱来付j-k*i*i的方法数不相等(当然也可以认为支付0元的方法为1)

相关推荐

    DP入门_阮行止.pptx

    本课件主要通过一个经典的硬币找零问题来介绍DP的基本概念和应用。 在DP入门中,我们首先面临的问题是:给定一系列不同面值的硬币(如1, 5, 10, 20, 50, 100)以及一个目标金额,我们需要找到最少使用多少枚硬币来...

    coins.zip分治算法,求取最轻且价值最大的硬币集合

    在这个硬币问题中,我们可以创建一个二维数组dp,其中dp[i][j]表示前i个硬币中能组成总价值j的最小重量。初始状态下,dp[0][0]为0,表示没有硬币时重量为0。 接下来,我们遍历所有的硬币,对于每个硬币,我们有两种...

    钱币组合方法数的问题

    在计算机科学领域,"钱币组合方法数的问题"是一个经典的动态规划问题,通常出现在算法分析与设计的课程中。这个问题涉及到如何计算使用不同面值的钱币来组成特定金额的所有可能组合方式。在这里,我们将深入探讨这个...

    php-leetcode题解之零钱兑换.zip

    首先,我们要了解“零钱兑换”问题的背景:给定一个非负整数n(代表金额)和一个数组coins(代表面额),目标是找到有多少种不同的方法可以凑成这个n,其中每种方法都由数组coins中的面额组成。这个问题可以被视为...

    coins-security-1.0.jar

    coins-security-1.0jar包

    donut2_Fifa_coins_

    标题 "donut2_Fifa_coins_" 暗示了我们正在讨论的是一款与FIFA游戏相关的项目,可能是一个自动购买FIFA游戏内货币(Coins)的程序或工具。FIFA游戏是由Electronic Arts (EA)开发的一款全球知名的足球模拟游戏系列,...

    8595钱币组合方法数的问题

    在这个钱币组合问题中,我们可以设立一个二维数组dp,其中dp[i][j]表示用前i种钱币组成j元的方法数。初始状态下,当j=0时,任何钱币都无法组成0元,所以dp[0][0] = 1;同样地,当i=0时,没有钱币可用,无论金额是...

    华为面试,分硬币

    对于硬币组合问题,我们可以定义一个动态规划数组dp[i],表示使用1分、2分和5分硬币组成i分的不同方法数。初始状态为dp[0] = 1(不使用任何硬币就是一种组合)。然后对于每个硬币面值,我们可以更新dp数组,如果当前...

    贪心算法java实现.docx

    1. **初始化**:定义一个`dp`数组,其中`dp[i]`表示凑成金额`i`所需要的最小硬币数。初始情况下,除了`dp[0]=0`外,其他值均设置为一个较大的数(这里设置为`amount+1`)。 2. **计算最少硬币数**:通过两层循环...

    2019 Standard Catalog of World Coins, 2001-Date, 13th edition

    根据提供的文件信息,可以看出这份文档并非关于《2019 Standard Catalog of World Coins, 2001-Date, 13th edition》的内容,而是关于一个特定软件或系统的功能需求文档。由于文档内容与标题及描述不相符,这里将...

    python-leetcode面试题解之第322题零钱兑换.zip

    给定不同面额的硬币coins和一个总金额amount,编写一个函数来计算可以凑成总金额所需的最少硬币个数。如果无法凑出指定金额,则返回-1。 **问题分析:** 这道题的关键在于找到一个最优化的方法来组合硬币以达到目标...

    Python 硬币兑换问题

    硬币兑换问题: 给定总金额为A的一张纸币,现要兑换成面额分别为a1,a2,….,an的硬币,且希望所得到的硬币个数最少。 # 动态规划思想 dp方程式如下 # dp[0] = 0 # dp[i] = min{dp[i - coins[j]] + 1}, 且 其中 i &gt;=...

    确定将一定数量的钱比如100,换成1,2,5,10,20,50元的组合问题(4)

    在这个问题中,我们可以创建一个二维数组dp,其中dp[i][j]表示用前i种面额的硬币组成金额j的组合数。 首先,初始化dp数组,dp[0][0]为1,表示没有使用任何硬币时,有1种组合(即金额为0)。对于每一种面额的硬币,...

    c++硬币找钱问题.rar

    对于硬币找钱问题,我们可以创建一个数组dp,其中dp[i]表示组成金额i所需的最少硬币数。 以下是C++代码的一个简要框架: ```cpp int coinChange(vector&lt;int&gt;& coins, int amount) { vector&lt;int&gt; dp(amount + 1, ...

    C++中拆分钱币问题

    在这个问题中,我们可以创建一个二维数组dp,其中dp[i][j]表示用前i种钱币凑出j元钱的最少硬币数量。初始化时,dp[0][j] = ∞(无穷大),因为没有使用任何钱币无法凑出任何金额;dp[i][0] = 0,因为不需凑出0元钱。...

    确定将一定数量的钱比如100,换成1,2,5,10,20,50元的组合问题(2)

    在这个问题中,我们可以定义一个二维数组`dp`,其中`dp[i][j]`表示使用前`i`种面值的硬币组成`j`元的最小硬币数量。初始状态`dp[0][0]`为0,因为不使用任何硬币就无法组成任何金额。对于`dp[i][j]`,我们可以有两种...

    确定将一定数量的钱比如100,换成1,2,5,10,20,50元的组合问题(3)

    在这个问题中,我们可以创建一个二维数组dp,其中dp[i][j]表示使用前i种硬币可以组成j元钱的组合数。初始化时,dp[0][0] = 1,因为不使用任何硬币时,组成0元钱有一种方法,即不选任何硬币。对于每个硬币面值,我们...

    算法最少硬币问题题目

    在这个问题中,我们将通过递归地解决找零的子问题,逐步构建一个全局最优解。 **问题定义**: - 设 `dp[i]` 为找零 `i` 面额所需的最少硬币数。 - 对于每一种硬币面值 `t`(`t` 在 `T` 中),我们考虑用 `Coins[t]`...

    假设有人民币10的n次方(变量值),输出1元,2元,5元的所有组合数

    在这个问题中,我们可以定义一个数组dp,其中dp[i]表示组成i元所需要的组合数。初始状态为dp[0]=1,表示组成0元的组合数为1(即不使用任何硬币)。然后,我们可以遍历所有硬币的面额,更新dp数组,最终dp[10^n]就是...

    最小硬币问题的c语言代码

    在这个代码中,我们首先定义了一个硬币面值的数组`coins`,然后创建了一个动态规划数组`dp`,用于存储到达每个目标金额所需的最小硬币数。`dp[0]`初始化为0,表示没有金额不需要任何硬币。接下来,我们通过两个嵌套...

Global site tag (gtag.js) - Google Analytics