Algorithm 有限制地将n个数与k求和的方法数

Algorithm 有限制地将n个数与k求和的方法数,algorithm,data-structures,dynamic-programming,backtracking,Algorithm,Data Structures,Dynamic Programming,Backtracking,我正在努力为以下问题找到DP递归: 给定N个连续正数和M的区间,找出从N个给定区间到k的每个区间中N个数求和的可能性有多少 例如: n = 2, k = 4 where the n intervals are: [0, 1, 2] [0, 1, 2] 所以只有一个有效的解决方案2+2 我正在寻找一种自下而上的方法。 这就是我尝试过的: long getPossibilities(int N, int M, vector<vector<int>> &limits)

我正在努力为以下问题找到DP递归: 给定N个连续正数和M的区间,找出从N个给定区间到k的每个区间中N个数求和的可能性有多少

例如:

n = 2, k = 4
where the n intervals are:
[0, 1, 2]
[0, 1, 2]
所以只有一个有效的解决方案2+2

我正在寻找一种自下而上的方法。 这就是我尝试过的:

long getPossibilities(int N, int M, vector<vector<int>> &limits) {
vector<vector<long>> dp (N, vector<long>(M + 1, 0));

for(int i = 0; i < N; i++) {
    for(int k = limits[i][0]; k <= limits[i][1]; k++){
        dp[0][k] = 1;
    }
}

for(int i = 1; i < N; i++) {
    for(int j = 1; j <= M; j++) {
        dp[i][j] = dp[i - 1][j];
        for(int k = limits[i][0]; k <= limits[i][1]; k++) {
            if(j - k >= 0) {
                dp[i][j] = (dp[i][j] + dp[i][j - k]) % 1000000007;
            }
        }
    }
}
return dp[N - 1][M];
}

有什么建议吗?

我假设所有间隔条目都是正值。一种动态规划方法是将状态表示为n,t,其中n是当前间隔的指数,t是目标和。例如,示例中的初始状态为n=0,t=4

设fn,t表示从区间n到最后一个s.t选择一个元素的方法的数量。所选元素的总和为t。然后,在伪代码中

f(n, t) = sum(f(n+1), t - row[n][j]) for j <= len(row[n]))
如果有一个数组A[i][j],表示与第一个j范围求和i的方法的数量,并且j+1范围是从A到b,则有以下关系:

A[i][j+1] = sum(A[x][j] for x = i-a to i-b)
将越界读取视为0

如果b-a较大,此更新步骤可能会占用OM^2时间,这可能就是解决方案超时的原因。通过首先计算累积和可以避免这种情况:对于i'=0到i,设B[i][j]=sumA[i'][j]

然后A[i][j+1]=B[i-A][j]-B[i-B-1][j]*

这一进程将是:

如果i=0,则以[i][0]=1开头,否则为1 设置j=0 通过对A[j][j]的元素求和,计算从0到M的每个i的B[i][j]。 使用公式*计算从0到M的每个i的[i][j+1]。 增加j,直到j=n+1。 返回到步骤3。 完成后,结果是[M][n]


如果你聪明的话,你可以使用一个M大小的数组,而不是两个M×n大小的数组。

这实际上是我尝试的第一种方法。但是,我收到一个超过时间限制的警告。这就是为什么我要寻找一种自下而上的方法。我的递归公式是dp[i][j]=dp[i-1][j]+j>=k?dp[i][j-k]:0;其中i是n级,j是当前目标,k是xs中的当前元素。但我认为我没有弄好。你可能想用完整的问题陈述更新你的问题,包括modus计算和你迄今为止尝试过的代码。谢谢。有些考试我还是答错了。当我试着打印A时,结果是这些测试的正确答案,如果我多运行一个步骤,只有10/45的测试才是[M+1][N]。你知道为什么吗?
A[i][j+1] = sum(A[x][j] for x = i-a to i-b)