卡片,袋子和硬币的复发关系理解

时间:2017-06-25 20:44:14

标签: algorithm dynamic-programming subset-sum recurrence

https://www.codechef.com/problems/ANUCBC基本上归结为以下内容:

给定n个整数的数组A和正整数m(1 <= m <= 100),找到该数组的可被m整除的子集数。

递归关系: 设dp [i] [j]表示包含元素中的元素的子集数量,这些元素在数组中的第i个元素,并且当我分割时,元素的总和为余数j。

dp(i,j)= dp(i-1,j)+ dp(i-1,(j-a [i])%m)

然而,我无法理解j-a [i]部分。让我解释清楚为什么我被困在一个例子。

[6,7,7]和m = 5

假设我们在索引0处:我们需要的是知道该数字是否可被5整除。如果没有,只要知道它返回什么模式并记住它。

dp [0] [1]应为真,因为它留下1的余数(6%5)。

索引1也是如此:dp [1] [2]将为7%5 = 2。我们还需要知道记录dp [1] [3]与添加(6 + 7)%5 = 3一样真实。

但是,在索引2处,我们需要知道过去的结果dp [1] [3],以便将dp [2] [0]视为真,因为(3 + 2)%5为0。

任何人都可以帮助我理解这一点,我花了无数个小时没有太多进展。

还有一个问题是负面的mods。如何处理这种递归关系?

1 个答案:

答案 0 :(得分:0)

要首先了解解决方案,您需要了解以下内容 -

使用i项设置的set子集(假设这组子集为 I )是 -

的联合

1)具有i-1项目的集合子集。让这组子集用 J 表示。

2)所有这些子集(步骤1)与第i个元素的联合。让这组子集用 K 表示。

示例 - 让项目为[1,2,3]

现在,包含2个项目的集子集是 - {},{1},{2},{1,2}, J

所以, K = {3},{1,3},{2,3},{1,2,3}

I = J + K

让我们现在转到您的问题。

类似或者你可以称之为移动方法dp[i][j](或)是dp[i-1][j](或 J )加上ķ

K 可以找到 J 中的第i个元素,即dp[i-1][(j-a[i])%m]。现在,因为我们已经包含了第i项而不是我们需要添加的数字,所需的数额将是和 - 已经包含的第i项的值。这是使用(j-a[i])

的原因

如何获得绝对值 - 只需创建一个返回给定数字绝对值的函数,并在您认为可能需要的地方使用它。

这是函数的代码 -

int abs(int x){
     return x>0?x:-x;
}