TODO: 动态规划到底是个什么玩艺?
ref:http://www.cnblogs.com/waytofall/archive/2012/04/10/2439820.html
I 只考虑怎样产生更大的子组和:
假设处理到第i个节点时:
1. 考虑是否i节点是否可使子组的和变大
a) 如果i节点大于0,则最大子组和是前面求到的数组和 加上 i节点值
b) 如果i节点小于0(等于0的话,值可以带上i,也可以不带上i,无所谓),当最大子数组的和是前面求的子组和
2. 然后考虑最大值是否应该更新了
a) 如果当前子组和大于最大和,则更新
int // 动态规划法
get_max_sub(int a[], int len)
{
int max_sum, cur_sum;
int i;
max_sum = cur_sum = a[0];
i = 0;
while (++i < len) {
if (cur_sum > 0) {
cur_sum += a[i];
} else {
cur_sum = a[i];
}
if (cur_sum > max_sum) {
max_sum = cur_sum;
}
}
return max_sum;
}
II 再细化考虑子数组的前后边界
1. 因为子数组和是负时,则最大值就是i节点,则将左边界挪到i节点上。
2. 当i节点为负,(思维雷区!!),到于右边办什么时挪?当然是子数组和变大了再挪了(子和变大了,子数组扩张了)
int // 动态规划法
get_max_sub(int a[], int len, int <, int &rt)
{
int max_sum, cur_sum;
int i;
max_sum = cur_sum = a[0];
lt = rt = 0;
i = 0;
while (++i < len) {
if (cur_sum > 0) {
cur_sum += a[i];
} else {
cur_sum = a[i];
lt = i;
}
if (cur_sum > max_sum) {
max_sum = cur_sum;
rt = i;
}
}
return max_sum;
}
总结:
1. 思维深度一点点加深,由少及多
2. 摆脱思维惯性,避开雷区。
考虑最大子数组时,考虑的中心是历史子数组和是正还是负(即子数组和是当前第个i节点呢还是第i个节点加上以前的和呢),而不是只考虑加上i节点子数组是变大还是变小(直观/惯性思维引入雷区)