平衡石头

时间:2017-03-03 09:19:32

标签: c++ algorithm dynamic-programming

你有许多已知重量为w1,...,wn的宝石。编写一个程序,将石头重新排列成两堆,使两桩之间的重量差异最小。 我有dp算法:

int max(int a, int b){
    return a >= b ? a : b;
}

int diff(int* weights, int number_elements, int capacity){
    int **ptrarray = new int* [capacity + 1]; 

    for (int count = 0; count <= capacity; count++) {
        ptrarray[count] = new int [number_elements + 1];
    }

    for (int i = 0; i <= number_elements; ++i){
        ptrarray[0][i] = 0;
    }

    for (int i = 0; i <= capacity; ++i){
        ptrarray[i][0] = 0;
    }

    for (int i = 1; i <= number_elements; ++i){
        for (int j = 1; j <= capacity; ++j){
            if(weights[i - 1] <= j){
                ptrarray[j][i] = max(ptrarray[j][i - 1], ptrarray[j -    weights[i - 1]][i-1] + weights[i - 1]); 
            } else{
                ptrarray[j][i] = ptrarray[j][i - 1];
            }
        }
    }

    return ptrarray[capacity][number_elements];

}




int main(){ 
    int capacity;
    int number_elements;

    cin >> number_elements;

    int* weights = new int[number_elements];
    int sum = 0;
    int first_half;

    for (int i = 0; i < number_elements; ++i){
        cin >> weights[i];
        sum+=weights[i];
    }

    first_half = sum / 2;
    int after;

    after = diff(weights, number_elements, first_half);
    cout << sum - 2*after;
    return 0;
}

但它有点幼稚。它需要太多内存,我需要一些提示来简化它。有更有效的方法吗?

1 个答案:

答案 0 :(得分:2)

您可以通过进行以下观察来减少内存使用量:

  1. 您的代码随时只能使用ptrarray数组的最多两层。

  2. 如果从每个图层中的最大索引到最小索引进行迭代,则可以重写上一个图层。这样你只需要一个数组。

  3. 以下是具有此优化的伪代码:

    max_weight = new int[max_capacity + 1](false)
    max_weight[0] = true
    for weight in weights:
         for capacity in [max_capacity ... weight]:
              max_weight[capacity] = max(max_weight[capacity], max_weight[capacity - weight] + weight
    

    它需要O(max_capacity)内存(而不是O(max_capacity * number_of_items))。

    还有一些优化:你可以使用一个布尔数组(来指示和i是否可达)并在最后选择最大的可达总和,而不是存储小于或等于{的最大和。 {1}}。此外,您可以使用i而不是布尔数组来获得std::bitset时间复杂度(其中O(max_capacity * num_items / world_len)是机器可以执行逻辑运算的最大整数类型的大小) 。添加一个权重看起来像world_len

    所以最终版本看起来像这样:

    reachable |= (reachable << weight)

    这种方式变得更加简单和高效(时间复杂度在技术上是相同的,但在实践中要快得多)。

    这里有一点需要注意:你需要在编译时知道reachable = bitset(max_capacity + 1) reachable[0] = true for weight in weights: reachable |= reachable << weight return highest set bit of reachable 的大小,所以如果不可能,你需要一个不同的bitset实现。