可以减少并改造为背包吗?

时间:2016-09-20 22:44:17

标签: algorithm recursion dynamic-programming knapsack-problem powerset

我想知道可以将powerset问题转化并减少到背包问题吗?在我看来,它们是相同的,例如我们可以将其视为powerset的变化,每个递归阶段我发起2个递归调用(一个采用i元素,另一个绕过它)。我也可以用动态编程解决它,就像背包问题一样,这让我想知道是否所有的powerset问题都可以转化为背包问题。那是对的吗 ?

以下是硬币变化的代码片段,其中一个具有O(2 N )时间复杂度,另一个具有动态编程O(N 2 )运行时。

// O(2^N) time complexity
void bruteforce(int[] coins, int i, int N, String expr) 
{
     if (i == coins.length) {
         if (N == 0)
            count++;
         return;
     }

     if (N >= coins[i])
         recursion(coins, i, N - coins[i], expr + " " + coins[i]);
     recursion(coins, i + 1, N, expr);
}

// O(N^2) time complexity
int dynamicProgramming(int[] coins, int N) 
{
     int [] dp = new int[N + 1];
     dp[0] = 1;

     for(int i = 0; i < coins.length; i++)
         for(int j = coins[i]; j <= N; j++)
             dp[j] += dp[j - coins[i]];
     return dp[N];
}

1 个答案:

答案 0 :(得分:3)

查找powerset(生成集合的所有子集)不能以比O(2 n )更好的复杂度的方式完成,因为有2 n < / sup>子集并且仅打印它们将需要指数时间 诸如子集和,背包或硬币变化之类的问题与powerset有关,因为你 implicity 必须生成所有子集,但它们和powerset之间存在很大差异。在这些问题中,您只计算一些子集,并且您不需要明确生成这些子集。例如,如果问题要求您找到将X美元更改为某些硬币的所有方法,那么您无法在线性时间内解决此问题,因为您必须生成所有所需的子集,并且可能有2 n < / sup>他们。