【动态规划】 换钱方法

【动态规划】 动态规划最重要的两个问题就是  状态的定义 和 状态转移方程的定义。


/*****************************
换钱方法
给定数组arr,arr中所有的值都是整数且不重复,每个值代表一种面值的货币,
每种面值的货币可以使用任意张,再给定一个整数,aim代表要找的钱数,求换钱有多少种方法。
***********************************/
思路:
1,对 arr 从小到大排序。
2,建一张二维表 dp[m][n+1],其中 m 表示 arr 中货币的种类数, n 表示 aim。
   如:arr={2,3,4}, aim=5;
      
      | 0 1 2 3 4 5
    --|---------------
    2 | 1 0 1 0 1 0
    3 | 1 0 0 0 0 0
    4 | 1 0 0 0 0 0
      |
3,状态:    初始化 dp 表, dp[i][j] 表示目标钱数 j 用 arr[0],...,arr[i] 对应的货币来换的方法数。例如 dp[4][1] 表示用 2和3 换
  货币 4 的方法数。
4,状态转移:填充 dp 中的其他元素
   dp[i][j]=dp[i-1][j]+dp[i][j-arr[i]]


时间复杂度  O(m*n)

/***********************************
代码:

class Solution{
public:
    int changeMoneyWays(vector& array, int aim){
        sort(array.begin(), array.end());
        const int n = array.size();   //   构造二维 dp 的行
        const int m = aim + 1;        //    。。。。。。列
        vector> dp(n, vector(m, 0));        //   二维的 dp 数组
        for (int i = 0; i < n; ++i)                          //   初始化 dp 第一列
            dp[i][0] = 1;                            
        for (int j = 1; j < m; ++j) {                        //   初始化 dp 第一行
            if (!(j%array[0]))
                dp[0][j] = 1;
        }                         

        for (int i = 1; i < n; ++i){                         //  填充 dp 的其他部分
            for (int j = 1; j < m; ++j){

                dp[i][j] += dp[i - 1][j];                    //   状态转移
                if ( j >= array[i])
                    dp[i][j] += dp[i][j - array[i]];
            }
        }
        return dp[n - 1][m - 1];
    }
};


你可能感兴趣的:(【动态规划】 换钱方法)