【发布时间】:2015-09-18 06:04:40
【问题描述】:
我觉得 Kadane 的算法是最大子数组问题的真正动态规划解决方案的修改版。为什么我会这么觉得? 我觉得是因为计算最大子数组的方式可以采取:
for(i=0;i<N;i++)
{
DP[i][A[i]]=true;
for(j= -ve maximum ;j<= +ve maximum ;j++)
if(DP[i-1][j])
DP[i][j+A[i]]=true;
}
如果有可能用以 i-1 个元素结尾的子数组形成 j,则我可以使用第 i 个元素形成 j+A[i]并且还通过在第 i 个位置开始一个子数组来单独形成 A[i] 最后我们可以在这个 DP 数组中搜索标记为 true 的最大值 j!
注意:DP[i][j] 表示是否可以使用以 i 结尾的子数组来生成 j!在这里我假设 j 也可以是负数。!现在可以很容易地推导出 sum+ 一个负数 i-1 th 位置的最大值 j 并将其与 i th 元素连接起来,这让我觉得这是一种贪婪的选择(只是因为最大值 + 元素给了我一个最大值)。
注意:我现在还没有研究过贪心算法,但我知道什么是贪心选择!
编辑:有人说我的算法没有任何意义,所以我试图发布我的代码以使自己清楚。我没有把 j 当作 -ve,因为它们没有成果。 我再说一遍,我的状态被定义为是否可以使用以 i 结尾的子数组来生成 j。
#include<bits/stdc++.h>
using namespace std;
int DP[101][101];
int main()
{
int i,j,ans=INT_MIN;
int A[]={3,-1,2,-1,5,-3};
int N=sizeof(A)/sizeof(int);
for(i=1;i<=N;i++)
{
if(A[i-1]>=0)
DP[i][A[i-1]]++;
for(j=0;j<=100;j++)
{
if(DP[i-1][j])
{
if(j+A[i-1]>=0)
DP[i][j+A[i-1]]++;
}
if(DP[i][j])
ans=max(ans,j);
}
}
cout<<ans<<"\n";
return 0;
}
输出 8
【问题讨论】:
-
为了清楚起见,我添加了我的代码!
-
动态编程是一种技术,它不是一种属性。您可以在任何地方使用动态编程来降低时间复杂度,而贪婪是一种属性。你可以说 Dijkstra 的算法是使用动态规划,当它将所有先前计算的距离存储在一个数组中,并使用它们来计算到下一个城市的最短距离。但是,与此同时,Dijkstra 的算法是贪心的。
-
我的问题不清楚吗?如果是,我很抱歉。我问kadane的算法也是贪心算法还是这个DP的优化形式?我这么说是因为如果我们只考虑我的解决方案中的最高 j,它将产生 kadane 的算法(并且也忽略负 j),其中 j 是可以使用子数组形成的总和。!由于属性最大总和 + 一些 > 较小的总和 + 相同的东西!我明白了你所说的@PhamTrung。
-
IMO,这不是贪婪,实际上是蛮力。 DP只是确保你不需要解决一个case两次,但基本上你还是需要检查所有case,每个状态
dp[i][j]一个一个填写。 -
通常,DP用于递归算法。你的 alg 和 Kadane 的都不是递归的.....
标签: algorithm dynamic-programming greedy