Coins
Time Limit: 3000MS | Memory Limit: 30000K | |
Total Submissions: 27686 | Accepted: 9368 |
Description
People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some coins.He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact price(without change) and he known the price would not more than m.But he didn't know the exact price of the watch.
You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins.
You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins.
Input
The input contains several test cases. The first line of each test case contains two integers n(1<=n<=100),m(m<=100000).The second line contains 2n integers, denoting A1,A2,A3...An,C1,C2,C3...Cn (1<=Ai<=100000,1<=Ci<=1000). The last test case is followed by two zeros.
Output
For each test case output the answer on a single line.
Sample Input
3 10 1 2 4 2 1 1 2 5 1 4 2 1 0 0
Sample Output
8 4
题意:
给出 N , M 代表有 N(1 ~ 100) 种钱币,和钱币总和 M (0 ~ 100000)。后给出 N 种钱币的价值 和 对应的数量,现要凑钱币,问能凑出 1 ~ M 中几种钱币,输出这个数。
思路:
DP。设 dp [ j ] 代表要凑足 i 价值的钱币最多剩下的钱币数。
1. dp [ j ] = m [ i ] ,当 dp [ j ] >= 0 时;
2. dp [ j ] = -1,当 j < v [ i ] || dp [ j - v[ i ] ] <= 0 时;
3. dp [ j ] = dp [ j - v [ i ] ] - 1,其他情况。
初始化时,dp 都为 -1,标记为都不可到达状态,只有 dp [ 0 ] = 0,代表可以到达。若初始化为 0,则只会一直执行 1 公式,最终所有的钱币都能凑成,明显不对。
dp 过程中,曾经到凑成过的钱币知道最后循环循环结束都是能到达的,至于不能到达的,中途通过式子 3 可以更新得到。
AC:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n, m, ans; int v[105], num[105]; int dp[100005]; void solve() { memset(dp, -1, sizeof(dp)); dp[0] = 0; for (int i = 1; i <= n; ++i) { for (int j = 0; j <= m; ++j) { if (dp[j] >= 0) dp[j] = num[i]; else if (j < v[i] || dp[j - v[i]] <= 0) dp[j] = -1; else dp[j] = dp[j - v[i]] - 1; } } for (int i = 1; i <= m; ++i) if (dp[i] >= 0) ++ans; } int main() { while (~scanf("%d%d", &n, &m) && (n + m)) { ans = 0; for (int i = 1; i <= n; ++i) { scanf("%d", &v[i]); } for (int i = 1; i <= n; ++i) { scanf("%d", &num[i]); } solve(); printf("%d\n", ans); } return 0; }
相关推荐
这种算法的时间复杂度是O(w * coins),其中`coins`是硬币的种类数。相比于暴力枚举所有组合,它更快是因为我们只计算每个子问题一次,并存储结果供后续使用。这个过程体现了DP的两个关键特性:无后效性和最优子结构...
dp[i][j] = min(dp[i][j], dp[i-1][j], dp[i][j-v[i]] + 1) ``` 这里,dp[i-1][j]表示不使用第i个硬币的情况,而dp[i][j-v[i]] + 1表示使用第i个硬币的情况。遍历所有硬币和所有可能的总价值后,dp[n][Y]就会给出...
例如,16 coins 表示8个双线圈电磁阀。 6. **模块选择**:如果模块是连体的,如SMC阀岛的输入/输出模块X36/X37,需要在"Moudles"中选择对应的输入型号。 7. **下载与文件管理**:组态完成后,通过"Download—...
2. 如果可以使用第i种硬币,尝试将其加入组合,更新dp[i][j]为min(dp[i][j], dp[i][j-coins[i-1]] + 1)。 最后,dp[coins.length][amount]就是我们需要的答案,如果为正数则表示可以凑出金额,否则返回-1。 **...
# dp[i] = min{dp[i - coins[j]] + 1}, 且 其中 i >= coins[j], 0 <= j < coins.length # 回溯法,输出可找的硬币方案 # path[i] 表示经过本次兑换后所剩下的面值,即 i - path[i] 可得到本次兑换的硬币值。 ...
在遍历结束后,dp数组的最后一项dp[coins.length][n]就是所求的方法数。 以下是PHP代码实现的一个示例: ```php function change($n, $coins) { $dp = array_fill(0, $n + 1, array_fill(0, count($coins) + 1, 0...
`dp[i][j] = min{ dp[i][j], dp[i-coins[k]][j-1] + 1 }` 其中,`i`是总金额,`j`是硬币数量,`coins[k]`是当前考虑的硬币面值。`dp[i][j]`表示找零`i`元时使用`j`个硬币的最小数量。遍历所有可能的硬币面值,直到...
dp[i] += dp[i - coins[j]]; } } } return dp[target]; } int main() { int coins[] = {1, 2, 5}; int target = 10; cout (target, coins) ; return 0; } ``` 这个代码首先初始化一个dp数组,并设置dp[0]...
二是使用第`i`种面值的硬币,此时`dp[i][j]`是`dp[i][j-coins[i]] + 1`与`dp[i-1][j]`中的较小值,其中`coins[i]`表示第`i`种硬币的面值。 标签中的“源码”意味着这个问题可以通过编程语言实现,而“工具”可能指...
while (temp >= coins[j] && dp[temp] == dp[temp - coins[j]] + 1) { result[dp[amount] - 1] = coins[j]; temp -= coins[j]; dp[amount]--; } } return result; } } ``` 1. **初始化**:定义一个`dp`...
dp[i][j] = dp[i][j-1] + dp[i-coins[j-1]][j] ``` 这个方程表示:当前金额`i`的组合数等于不使用第`j`种钱币的组合数(即使用前`j-1`种钱币组成`i`的组合数)加上使用第`j`种钱币且剩余金额为`i-coins[j-1]`的...
dp[i] = min([dp[i-c] if i-c >= 0 else float('inf') for c in coins]) + 1 return dp[amount] if dp[amount] != float('inf') else -1 ``` 自底向上的方法同样适用于解决找零问题,通过迭代计算出每个金额所需的...
假设我们有硬币面值`coins`和每种硬币的最大数量`maxCounts`,我们可以按照以下步骤建立DP模型: 1. 初始化`dp`数组,对于所有`j`,`dp[0][j] = ∞`,表示不使用任何硬币时无法支付任何金额。`dp[i][0] = 0`,表示...
dp[i][j] = dp[i-1][j] + (j >= coins[i-1] ? dp[i][j-coins[i-1]] : 0); } } return dp[n][amount]; } public static void main(String[] args) { int[] coins = {1, 2, 5, 10, 20, 50}; int amount = 100...
dp[i][j] = dp[i-1][j] + dp[i][j-coins[i]] (j >= coins[i]) 最后,dp[n][8595]就表示用所有n种钱币组成8595元的方法数。这个过程可以通过迭代或递归实现,但迭代通常更有效,因为它避免了重复计算。 在实际...
dp[i][j] = min(dp[i][j], dp[i - 1][j] + dp[i][j - coins[i]]) ``` 这个过程确保了我们始终选择最优解,即使用当前硬币面值或者不使用它。最后,`dp[-1][-1]`就是我们要找的答案。 找零钱问题的动态规划解法...
\[ dp[i] = dp[i] + dp[i - coin] \] 其中,coin表示当前考虑的硬币面额,这个公式的意思是,如果可以通过某种方式使用一个面额为coin的硬币到达i元,那么dp[i]就应该加上dp[i-coin],即通过使用一个coin硬币达到i...
在这个问题中,我们可以创建一个二维数组dp,其中dp[i][j]表示用前i种面额的硬币组成金额j的组合数。 首先,初始化dp数组,dp[0][0]为1,表示没有使用任何硬币时,有1种组合(即金额为0)。对于每一种面额的硬币,...
- 如果 `i >= t` 且 `Coins[t] > 0`,更新 `dp[i] = min(dp[i], dp[i - t] + 1)`。 3. 返回 `dp[Money]` 作为最少硬币数。如果 `dp[Money] == Integer.MAX_VALUE`,则输出 `-1` 表示无解。 **输入输出处理**: - ...