牛客网NC77-20.7.23-dp(动态规划())

链接:牛客网NC77链接
题意:
牛客网NC77-20.7.23-dp(动态规划())
文章图片

输入:n,x,a[] (n<=20,x<=100,a[i][0]<=50,a[i][1]<=20)
输出:方法数
分析:想象这些钱是一堆一堆的,相同的钱放在一堆里面,有n堆,然后一个从第一堆开始拿钱,直到拿到的钱的值之和等于目标面值x, 在每一堆钱面前有着多种拿法,可以拿一张,两张…只要目标钱数-已经拿的钱数>=要拿的张数面值,这样在一堆面前有着多种状态,可以用递归实现状态的前进与后退,分析一下,最坏情况堆钱有w种拿法,递归n层,wn次递归,w<=20,n<=20,最坏2020,嗞,得,完蛋了。幸好奥,这种状态得转换还可以通过dp来达到,我还记得以前看的书说了,对于动态规划,一是要明确状态,二是要得到状态转移。我们可以定义状态dp[i][j]是有i种牛币目标币值j的换钱方法,所以初始状态是什么呢,是0种牛币目标币值0的换钱方法为1,即是dp[0][0]=1,当然dp[i][0]当然都是0,当时我也有这样的疑问,看似初始状态有很多,但总有一个或几个是不能被其他状态转移的,这才是初始状态,看一下状态转移方程是怎么样的呢,从dp[i][j]能转移到什么地方呢?dp[i][j]可以转移到
dp[i+1][j+k*a[i+1][0]],k∈ \in ∈[0,a[i+1][1]]是拿取得第i+1种的钱币数,a[i+1][0]是第i+1种牛币的币值,a[i+1][1]是第i+1种牛币的数量,找找还有其他的转移吗,没了就得到如下状态转移方程:
dp[i+1][j+k*a[i+1][0]+=dp[i][j], k∈ \in ∈[0,a[i+1][1]]j+k*a[i+1]<=x
当然,我想过,如果想想,dp[i]][j]可以由什么地方转移过来呢,看似是这样:
dp[i][j]=dp[i-1][j-k*a[i][0]],k∈ \in ∈[0,a[i+1][1]]j+k*a[i+1]<=x
但是实际上dp[i-1][j-k*a[i][0]]的状态没有得到,所以这样是错误的。
思路:坐下来冷静分析然后dp
代码:

import java.util.*; public class Solution { /** * * @param n int整型 :牛币值种类数 * @param x int整型 :牛妹拥有的钱数 * @param a int整型二维数组 :第二个vector中的第一列表示币值,第二列表示牛牛拥有币值的个数 * @return int整型 */ public int solve (int n, int x, int[][] a) { // write code here int[][] dp = new int[n+1][x+1]; dp[0][0]=1; for(int i=0; i

【牛客网NC77-20.7.23-dp(动态规划())】等下你电瓶车就不见…

    推荐阅读