POJ 2923 Relocation(状态压缩+01背包)

来源:互联网 发布:抽烟的危害知乎 编辑:程序博客网 时间:2024/05/01 12:56


Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 2363 Accepted: 978

Description

Emma and Eric are moving to their new house they bought after returning from their honeymoon. Fortunately, they have a few friends helping them relocate. To move the furniture, they only have two compact cars, which complicates everything a bit. Since the furniture does not fit into the cars, Eric wants to put them on top of the cars. However, both cars only support a certain weight on their roof, so they will have to do several trips to transport everything. The schedule for the move is planed like this:

  1. At their old place, they will put furniture on both cars.
  2. Then, they will drive to their new place with the two cars and carry the furniture upstairs.
  3. Finally, everybody will return to their old place and the process continues until everything is moved to the new place.

Note, that the group is always staying together so that they can have more fun and nobody feels lonely. Since the distance between the houses is quite large, Eric wants to make as few trips as possible.

Given the weights wi of each individual piece of furniture and the capacitiesC1 andC2 of the two cars, how many trips to the new house does the party have to make to move all the furniture? If a car has capacityC, the sum of the weights of all the furniture it loads for one trip can be at mostC.

Input

The first line contains the number of scenarios. Each scenario consists of one line containing three numbersn,C1 and C2. C1 andC2 are the capacities of the cars (1 ≤Ci ≤ 100) andn is the number of pieces of furniture (1 ≤n ≤ 10). The following line will containn integers w1, …,wn, the weights of the furniture (1 ≤wi ≤ 100). It is guaranteed that each piece of furniture can be loaded by at least one of the two cars.

Output

The output for every scenario begins with a line containing “Scenario #i:”, wherei is the number of the scenario starting at 1. Then print a single line with the number of trips to the new house they have to make to move all the furniture. Terminate each scenario with a blank line.

Sample Input

26 12 133 9 13 3 10 117 1 1001 2 33 50 50 67 98

Sample Output

Scenario #1:2Scenario #2:3

Source

TUD Programming Contest 2006, Darmstadt, Germany

解题报告:

题意是给n个物品(n<10),每个物品有一定重量。给两辆车,两辆车分别有最大载重。问需要几次才能把物品从A运到B。先枚举出所有能够一次运过去的组合,这些组合用二进制表示1表示被运输,0表示不被运输。那么最多有2^n-1个选择,从中找出这些组合就可以了。(状态压缩)

然后用这些组合去拼凑出11……1共n个·1这个状态(全部运过去的情况),dp表示达到这个状态最少需要几次运输。要注意的是组合的两个状态必须是没有交集的,即一个物品只能运一次。所以dp递推为

if(!(way[i] & j)) {                    dp[j|way[i]] = std::min(dp[j|way[i]], dp[j] + 1);                }

其中,条件是当前要运输的组合way[i]与原dp[j]没有交集。那么久更新dp[j|way[i]]组合。目标是dp[2^n-1]的最小值。

其中(1<<n)表示2^n,x&(1<<i)表示x的第i个二进制位是否为1.

#include <cstdio>#include <cstring>#include <algorithm>const int oo = 0xfffffff;int n, c1, c2, w[11], dp[1 << 10], one[1 << 10], way[1 << 10];bool oneTrip(int x) {    memset(one, 0, sizeof(one));    int sum = 0;    for (int i = 0; i < n; i ++) {        if (x & (1 << i)) {            sum += w[i];            for (int j = c1; j >= w[i]; j --) {                one[j] = std::max(one[j], one[j - w[i]] + w[i]);            }        }    }    if(sum - one[c1] <= c2) {        return true;    }    return false;}int main() {    int t;    scanf("%d", &t);    int cnt = 0;    while (cnt < t) {        scanf("%d%d%d", &n, &c1, &c2);        for (int i = 0; i < n; i ++) {            scanf("%d", w + i);        }        int k = 0;        std::fill(dp, dp + (1<<n), oo);        for (int i = 0; i < (1<<n); i ++) {            if(oneTrip(i)) {                way[k ++] = i;                dp[i] = 1;            }        }        for (int i = 0; i < k; i ++) {            for (int j = (1<<n)-1; j >= 0; j --) {                if(!(way[i] & j)) {                    dp[j|way[i]] = std::min(dp[j|way[i]], dp[j] + 1);                }            }        }         printf("Scenario #%d:\n%d\n\n", ++ cnt,dp[(1<<n)-1]);    }    return 0;}


0 0
原创粉丝点击