如何理解动态规划中的线性分区

时间:2017-03-30 06:45:14

标签: arrays dynamic-programming

前几天我学到了线性分区问题,这是我的代码,这个代码是对的,我不理解它背后的公式,为什么会这样,如果你能够请解释我为什么这个公式有效。

for(int i=1;i<=n;i++) {
    rsq[i]=rsq[i-1]+arr[i];
}

int dp[n+1][k+1];
for(int i=0;i<=n;i++) {
    for(int j=0;j<=k;j++) {
        dp[i][j]=987654321;
    }
}
dp[0][0]=0;
for(int i=1;i<=n;i++) {
    dp[i][1]=rsq[i];
}
for(int i=1;i<=k;i++) {
    dp[1][i]=arr[1];
}

for(int i=2;i<=n;i++) {
    for(int j=2;j<=k;j++) {
        for(int x=1;x<i;x++) {
            int s=max(dp[x][j-1], rsq[i]-rsq[x]);
            if(dp[i][j]>s) dp[i][j]=s;
        }
    }
}
cout<<dp[n][k];

提前致谢。

1 个答案:

答案 0 :(得分:1)

遵循this解释,显然状态空间dp的语义如下;显然arr包含要处理的项目的大小,rsq包含下面所需的部分金额以避免重新计算。

dp[i][j] = minimum possible cost over all partitions of
           arr[1],...arr[i] into j ranges
           where i in {1,...,n} and j in {1,...k} or positive
           infinity if such a partition does not exist

显然在实现中987654321用于模拟正无穷大的值。注意,在说明中,与原始问题中的实现相比,状态空间的轴被交换。根据这个定义,我们得到了状态值的以下递推关系。

dp[i,j] = min{ max{ dp[i-1,j'], sum_{i'=j'+1}^{n} arr[i']} : j' in {1,...,j} }

在实施中,上述总和在rsq中预先计算。递归关系可以解释如下。给定dp[i-1][*]的某些特定值的i的所有值(这意味着项1的所有成本值已知i-1),所有值{{1} (对于dp[i][*]项目最多1),可以通过从ij'+1n'范围从j'j的所有项目获取j,考虑所有可能性)并总结剩余项目(然后构成一个分区);对于第一项的最佳分区,使用预先计算的值。这些值的最大值是选择的成本。

直观地说,这可以看作是在任意分割点对项arr[1],...,arr[n]进行分区。右边的项目被视为一个分区(其成本是它们的成员之和,因为它们被放在一个分区中),左边的项目被最佳地递归分区为一个分区。动态编程算法(除了部分和的预先计算之外)初始化一些基本情况,这些基本情况与将每个项目放在单个分区中相对应,并组织状态的评估顺序,使得下一个更大的值所需的所有值{始终在需要时计算第二轴的{1}}。