LintCode刷题笔记-- BackpackIV

标签:

动态规划

描述:

Given an integer array nums with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.

Example

Given nums = [1, 2, 4], target = 4

The possible combination ways are:
[1, 1, 1, 1]
[1, 1, 2]
[1, 2, 1]
[2, 1, 1]
[2, 2]
[4]

return 6

解题思路:

这一题昨天真正纠结了一整天:最后看答案还是没有能够完全理解,幸亏飞飞指点迷津,现在多少有点儿眉目了。

对于,动态规划的问题其实不需要将所有的问题都展开成为二维的矩阵,一维的数组有时可以更好的解决问题,例如这一题,其实需要记录的就是达到target这一状态下需要可以有多少种可能,并不需要记录每个数字存在与否时的可能性。这样,需要维护的变量就会少很多。

另外,不需要强行去照搬套路,有的时候后续子问题和先前子问题不一定在任何情况下都存在关系,按照昨天讨论的结果,是0,他就是0,不要强行在dp[i]上找出与先前的关系。

关于DP是一种思想,最重要的是先前子问题与当前问题在逻辑上某种联系。个人理解,先前子问题可能是一个庞大而繁杂的动态规划问题,但是对于解决当前问题的时候先前问题任何庞大而繁杂的逻辑都体现为子问题最优解的一个节点,并与当前存在某种联系。这种联系称为状态转移方程。

对于本题:

1.子问题划分:

对于这一题只需要在target一个向量上进行划分,因为在每一个target上存在几个数字的可能性并不需要逐一记录,并且这些结果对于后续子问题并不存在实际意义

2.状态转移方程:

如果当前target的值大于nums中的某个数时,当前target上所有的存在解的数量应加上当前target-nums[j]位置上解的数量,因为结果集中加入nums[j]的时候,先前未加入时状态下的解全部需要叠加到当前位置上。

3.初始状态:

开始target为0时任何元素也不加入,存在一个空解,有dp[0]=1.

4.参考代码:

public int backPackVI(int[] nums, int target) {
        int[] dp = new int[target+1];
        dp[0] =1;
        for(int i = 1; i<=target; i++){
            for(int j =0; j<nums.length; j++){
                if(i>=nums[j]){
                    dp[i] += dp[i-nums[j]];
                }
            }
        }
        return dp[target];
    }

 

posted @ 2016-09-07 22:26  whaochen  阅读(606)  评论(0编辑  收藏  举报