小偷占用的最大价值

时间:2018-02-05 06:28:21

标签: algorithm data-structures dynamic-programming knapsack-problem greedy

考虑到我们有一大堆黄金和小偷希望得到最大的黄金。小偷可以拿金来获得最大值,

1)从连续的麻袋中取出黄金。

2)小偷应从所有麻袋中取出相同数量的金。

N Sacks 1 <= N <= 1000

M量的金0 <= M <= 100

示例输入1:

3 0 5 4 4 4

输出: 16

说明: 4是他从麻袋3到6中取出的最小值,以获得最大值16。

示例输入2: 2 4 3 2 1

输出: 8

说明: 2是他从麻袋1到4中取得的最小值,以获得最大值8。

我使用从数组中减去值并将转换点从负数转为正数来解决问题,但这并不能解决问题。

编辑:OP提供的代码,用于查找索引:

int temp[6]; 
for(i=1;i<6;i++){ 
    for(j=i-1; j>=0;j--) { 
        temp[j] = a[j] - a[i]; 
    } 
} 
for(i=0;i<6;i++){ 
    if(temp[i]>=0) { 
        index =i; 
        break; 
    } 
} 

2 个答案:

答案 0 :(得分:3)

从每个袋子中取出的最佳金量(TBAG)等于某些袋子的重量。让我们按顺序将候选人的索引放在一个堆栈中。

当我们遇到更重的重量(比堆栈包含)时,它肯定会继续&#34;良好的序列&#34;,所以我们只需将其索引添加到堆栈中。

当我们遇到较轻的重量(比堆叠顶部)时,它会打破一些好的序列&#34;我们可以从堆栈中删除较重的候选者 - 他们以后没有机会成为TBAG。移除堆栈顶部直到满足较轻的重量,在此过程中计算可能被盗的总和。

请注意,堆栈始终包含严格增加权重序列的索引,因此我们不需要在堆栈顶部(中间AG)的索引之前考虑项目来计算被盗总和(稍后将考虑使用另一个AG值)。

for idx in Range(Sacks):
     while (not Stack.Empty) and (Sacks[Stack.Peek] >= Sacks[idx]): //smaller sack is met
         AG = Sacks[Stack.Pop]
         if Stack.Empty then
            firstidx = 0
         else  
            firstidx = Stack.Peek + 1
         //range_length * smallest_weight_in_range
         BestSUM = MaxValue(BestSUM, AG * (idx - firstidx))  
     Stack.Push(idx)

now check the rest: 
  repeat while loop without >= condition 

每个项目都被按下并弹出一次,因此线性时间和空间复杂。

P.S。我觉得我在另一种表述中见过这个问题......

答案 1 :(得分:1)

我现在看到两种不同的方法:

天真的方法:对于数组中的每对索引(i,j),计算区间(i,j)中数组的最小值m(i,j)然后计算得分(i,j)= | j-i + 1 | * m(i,j)。然后取所有对(i,j)的最高分。

- &GT; O(n ^ 3)的复杂性。

不太天真的方法:

  1. 计算数组的值集

  2. 对于每个值,计算它可以获得的最高分数。为此,您只需要对数组的所有值进行一次迭代。例如,当您的样本输入为[3 0 5 4 4 4]并且您正在查看的当前值为3时,它将为您提供12分。(您将首先找到值3,这要归功于第一个指数,然后由于指数从2到5而得分为12。

  3. 取最大值在步骤2中找到的所有值。

  4. - &GT;复杂度在这里是O(n * m),因为你必须在步骤2中进行最多m次,而步骤2可以在O(n)中完成。

    也许有更好的复杂性,但我还没有线索。