题意分析
- 给你一个序列,我们需要选取其中几个数字拼接成一个固定的数字,问不同的拼接方案?
思路分析 DP
解法一
首先,我们来分析一下,这个题目需要n种数字拼接成一个固定的数字x,假设我们当前已经知道了前i-1种数字的情况凭借成x的方案数,那么当我们枚举到第i种数字的时候,我们拼接的方案数就可以由前i-1种情况转移过来。具体的转移方程就是.初始条件为
代码如下
- 最外层每次次,第二层枚举次,里面枚举次,所以总的时间复杂度就是
- 状态方程定义为,前种硬币组合成的种类数,所以空间复杂度为
class Solution { public: /** * * @param n int整型 :牛币值种类数 * @param x int整型 :牛妹拥有的钱数 * @param a int整型vector<vector<>> :第二个vector中的第一列表示币值,第二列表示牛牛拥有币值的个数 * @return int整型 */ int dp[55][110]; int solve(int n, int x, vector<vector<int> >& a) { // write code here // 枚举使用的硬币的种类数 dp[0][0]=1; for(int i=1;i<=n;i++){ // 枚举前i种硬构成面值j的种类数 for(int j=0;j<=x;j++){ // 枚举当前这种硬币使用的个数 for(int k=0;k<=a[i-1][1]&&j-k*a[i-1][0]>=0;k++){ dp[i][j]+=dp[i-1][j-k*a[i-1][0]]; } } } return dp[n][x]; } };
解法二
我们使用滚动数组优化空间。我们观察上面的状态方程,我们发现,每种状态只能由上一个状态转移过来。所以其实我们状态方程的第一维可以定义为两个状态,但是在每次处理当前状态的时候我们需要将当前的状态先清0,防止之前的状态的影响。
如下图
所以其实这个状态i-1之前的是什么状态我们根本不关心,故可以进行上述优化
代码如下
- 最外层每次次,第二层枚举次,里面枚举次,所以总的时间复杂度就是
- 状态方程定义为,第种状态硬币组合成的种类数,所以空间复杂度为
class Solution { public: /** * * @param n int整型 :牛币值种类数 * @param x int整型 :牛妹拥有的钱数 * @param a int整型vector<vector<>> :第二个vector中的第一列表示币值,第二列表示牛牛拥有币值的个数 * @return int整型 */ int dp[2][110]; int solve(int n, int x, vector<vector<int> >& a) { // write code here // 枚举使用的硬币的种类数 memset(dp,0,sizeof(dp)); dp[0][0]=1; for(int i=1;i<=n;i++){ // 枚举前i种硬构成面值j的种类数 for(int j=0;j<=x;j++){ dp[i&1][j]=0; } for(int j=0;j<=x;j++){ // 枚举当前这种硬币使用的个数 for(int k=0;k<=a[i-1][1]&&j-k*a[i-1][0]>=0;k++){ dp[i&1][j]+=dp[(i-1)&1][j-k*a[i-1][0]]; } } } return dp[n&1][x]; } };
解法三
我们继续进行优化,我们观察第二种写法,我们发现,我们枚举x的硬币数对应的种类的时候,都是由x之前的状态转移过来的,所以其实我们没有必要考虑第一维。直接让第二维由之前的状态转移过来就行了。所以状态方程就变为一维的了。
代码如下
- 最外层每次次,第二层枚举次,里面枚举次,所以总的时间复杂度就是
- 状态方程定义为,硬币组合成的种类数,所以空间复杂度为
class Solution { public: /** * * @param n int整型 :牛币值种类数 * @param x int整型 :牛妹拥有的钱数 * @param a int整型vector<vector<>> :第二个vector中的第一列表示币值,第二列表示牛牛拥有币值的个数 * @return int整型 */ int f[120]; int solve(int n, int x, vector<vector<int> >& a) { // write code here memset(f,0,sizeof(f)); f[0]=1; for(int i=0;i<n;i++){ for(int j=x;j>0;j--){ // 这里注意k不能从0开始了,不然会重复计算 for(int k=1;k<=a[i][1]&&j>=k*a[i][0];k++){ f[j]+=f[j-k*a[i][0]]; } } } return f[x]; } };