zoukankan      html  css  js  c++  java
  • 【POJ 2923】Relocation

    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 capacities C1 and C2 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 capacity C, the sum of the weights of all the furniture it loads for one trip can be at most C.

    Input

    The first line contains the number of scenarios. Each scenario consists of one line containing three numbers nC1 and C2C1 and C2 are the capacities of the cars (1 ≤ Ci ≤ 100) and n is the number of pieces of furniture (1 ≤ n ≤ 10). The following line will contain n 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:”, where i 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

    2
    6 12 13
    3 9 13 3 10 11
    7 1 100
    1 2 33 50 50 67 98

    Sample Output

    Scenario #1:
    2
    
    Scenario #2:
    3

    大意:
        要搬运N个货物,每个货物有一定的重量,现在有2辆车,每辆车有一定的容量C1、C2,要求每辆车装载的货物重量之和不超过车的容量,两辆车一起搬运,求出最少的搬运次数。(N <= 10,C <= 100)
     
    分析:
        首先可以注意到货物的个数很少,只有10,那么可以考虑用状态压缩。
        将每一次搬运的方案(用0、1表示某个货物是否被选择)压缩成一个 sta,用数组存下所有可行的方案。
        判断一个方案可不可行,先用sum记下所有选中的货物的重量和,判断可以用背包来做,f[i]可以表示当背包容量为i时,在这个方案中可以装下的最大的质量,做完背包然后枚举i为1~C1,判断如果C2 >= sum - f[i],那么则该方案可行。
        找出所有可行方案后,再用背包来将状态000……000转移到111……111,转移方程如下:
              DP[i | sta[j]] = min (DP[i | sta[j]], DP[i] + 1)
        其中i为当前的状态(即当前哪些货物已经被搬运),j是枚举所有可行的状态,i | sta[j]表示搬运了这些货物后的状态,每次转移的代价为1,最后输出DP[(1 << N) - 1](即111……111)。
        题目不保证C1 < C2,特殊判断一下使C1 < C2 可以提高效率。
     
    代码:
     
     1 #include <cstdio>
     2 #include <cstring>
     3 int t, n, c1, c2, w[11], sta[1 << 11], cnt, dp[1 << 11];
     4 inline int max (int a, int b)
     5 {
     6     return a > b ? a : b;
     7 }
     8 inline int min (int a, int b)
     9 {
    10     return a < b ? a : b;
    11 }
    12 bool check (int s)
    13 {
    14     int f[110], sum = 0;
    15     memset (f, 0, sizeof (f));
    16     for (int i = 0; i < n; i++)
    17     {
    18         if (s & (1 << i))
    19         {
    20             sum += w[i];
    21             for (int j = c1; j >= w[i]; j--)
    22                 f[j] = max (f[j], f[j - w[i]] + w[i]);
    23         }
    24     }
    25     for (int i = 0; i <= c1; i++)
    26         if (c2 >= sum - f[i]) return 1;
    27     return 0;
    28 }
    29 int main ()
    30 {
    31     scanf ("%d", &t);
    32     for (int p = 1; p <= t; p++)
    33     {
    34         scanf ("%d %d %d", &n, &c1, &c2);
    35         c1 > c2 ? c1 ^= (c2 ^= (c1 ^= c2)) : 0; //swap
    36         for (int i = 0; i < n; i++)
    37             scanf ("%d", &w[i]);
    38         memset (dp, 63, sizeof (dp)); dp[0] = cnt = 0; 
    39         for (int i = 0; i < (1 << n); i++)
    40             if (check (i)) sta[cnt++] = i;
    41         for (int i = 0; i < (1 << n); i++)
    42             for (int j = 0; j < cnt; j++)
    43                 dp[i | sta[j]] = min (dp[i | sta[j]], dp[i] + 1);
    44         printf("Scenario #%d:
    %d
    
    ", p, dp[(1 << n) - 1]);
    45     }
    46     return 0;
    47 }
  • 相关阅读:
    1065 01字符串
    poj 1321 棋盘问题
    0608模拟算法试题
    唯一的雪花
    2969 角谷猜想
    0607枚举算法试题
    3162 抄书问题(划分dp)
    8782:乘积最大(划分dp)
    2985:数字组合
    3531:判断整除
  • 原文地址:https://www.cnblogs.com/lightning34/p/4309601.html
Copyright © 2011-2022 走看看