POJ1837 01 backpack

POJ1837

topic

  The effect that there is a "special" balance, the balance is distributed in different locations C ( \ (2 \ C Le \ Le 20 is \) ) hooks, hook position coordinates from -15 to +15 (- representative of the left arm, + on behalf of the right arm). You have G ( \ (2 \ G Le \ Le 20 is \) ) th weights, masses, from 1 to 25. Q C hooks position coordinates of a given mass of G weights, how many have you hung a way that balances the balance.

Sample Input

2 4 
-2 3 
3 4 5 8

Sample Output

2

  There are two kinds of suspension follows:
\ [\} the begin {Equation (-2) * (. 4 + +. 5. 3) + (. 3) * (. 8) = 0 \ Quad or \ Quad (-2) * (. 4 +. 8 ) + (3) * (3 + 5) = 0 \ end {equation} \]

Algorithm thinking

  Reference thought 01 backpack, this question of the weight in the backpack can be compared 01 items, this will be linked to weight problems will analogy article 01 backpack into the backpack on the hook of the balance. State definition 01 backpack: opt [i] [j] denotes the front i items placed capacity is the maximum value of j, the backpack can be obtained analogously to this question, opt [i] [j] species, i can be expressed before the i weight, then this question in j represent? This is really really want to say is a bad thought, if dynamic programming Jiaoshu may be easier to get out. Careful observation of this problem, questions asked how many ways the suspension balance "balance", ie balanced formula (1), that is, all multiplied by the corresponding weights linked to the quality of location coordinates and equal to zero, and we can let j denote this " and "then opt [i] [j] means that before i hang a weight on the balance, resulting in" and "j possible suspension for the way how many. Further recursion formulas can be deduced:
\ [\ opt the begin {} Equation [I] [J Hooks + [K] * weights [I]] opt = [I] [J + [K] * weights [I] Hooks] opt + [i -. 1] [J] \ Equation End {} \]
\ (hooks [k] \) is the k th link coordinates, \ (weight [i] \) represents the i-th mass of the weights, formula (2) briefly, when you put the weight hanging on the hook K i, "and" will be changed from J \ (J + [K] * weights [i] hooks \) , the i-th former Fa cause codes "and" to \ (j + hooks [k] * weights [i] \) hanging manner increase the \ (opt [i - 1] [j] \) species. Note marked red "increase" word, indicates that there may be other ways to achieve suspension \ (j + hooks [k] * weights [i] \)This value, it should - \ ([j] \ opt [1 i]) plus the previous value. And when you are ready to put the i-th weights, you can hang in any hook, so the \ (1 \ Le k \ Le C \) .

  Further, the input limiting the subject, the range may be determined for j: \ (- 15 \ times20 times25 = -7500 \ Le j \ 7500 Le = 15 \ times20 \ times25 \ \) , j is negative range includes, but opt array subscript index does not allow negative, so the range of j pan right 7500, the range becomes \ (0 \ Le j \ Le of 15,000 \) . When initializing the subject, opt [0] [7500] 1, showing when the weight is not put "and" mode 7500 for the suspension of one species. The final output is opt [g] [7500], g represents a weight put, "and" 7500 still, i.e. non-discharge state remains weights, i.e., an equilibrium state.

Code

Simple realization

Result: 1460kB, 47ms.

#include <stdio.h>
#include <iostream>

int c, g;
int hooks[20 + 5], weights[20 + 5];
int opt[20 + 5][15000 + 5];//最大右偏20*25*15=7500,最大左偏-7500。由于数组下标不能索引负数,整体向右偏移7500,得0-15000
int main() {
    scanf("%d %d", &c, &g);
    for (int i = 1; i <= c; i++)
        scanf("%d", &hooks[i]);
    for (int i = 1; i <= g; i++)
        scanf("%d", &weights[i]);
    opt[0][7500] = 1;//初始时,0件砝码是平衡的。
    for (int i = 1; i <= g; i++)
        for(int j = 0; j <= 15000; j++)//遍历所有可能出现的“和”
            if(opt[i - 1][j])
                for (int k = 1; k <= c; k++)
                    opt[i][j + hooks[k] * weights[i]] += opt[i - 1][j];
    printf("%d\n", opt[g][7500]);
}

Optimization about the number of cycles j

Result: 936kB, 16ms

#include <stdio.h>
#include <iostream>
#include <limits.h>

int c, g;
int hooks[20 + 5], weights[20 + 5];
int opt[20 + 5][15000 + 5];//最大右偏20*25*15=7500,最大左偏-7500。由于数组下标不能索引负数,整体向右偏移7500,得0-15000
int main() {
    scanf("%d %d", &c, &g);
    scanf("%d", &hooks[1]);
    int min_hook = hooks[1], max_hook = min_hook;
    for (int i = 2; i <= c; i++) {//找出最小的位置坐标和最大的位置坐标
        scanf("%d", &hooks[i]);
        if (hooks[i] < min_hook)
            min_hook = hooks[i];
        else if (hooks[i] > max_hook)
            max_hook = hooks[i];
    }
    int sum_weight = 0;
    for (int i = 1; i <= g; i++) {
        scanf("%d", &weights[i]);
        sum_weight += weights[i];//砝码质量和
    }
        
    opt[0][7500] = 1;//初始时,0件砝码是平衡的。
    for (int i = 1; i <= g; i++)
        for (int j = 7500 + sum_weight * min_hook; j <= 7500 + sum_weight * max_hook; j++)//j的遍历范围从所有砝码放在min_hook到所有砝码放在max_hook
            if (opt[i - 1][j])
                for (int k = 1; k <= c; k++)
                    opt[i][j + hooks[k] * weights[i]] += opt[i - 1][j];
    printf("%d\n", opt[g][7500]);
}

Guess you like

Origin www.cnblogs.com/wtyuan/p/12097094.html