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

Relocation
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3627   Accepted: 1489

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 mostC.

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

Source

TUD Programming Contest 2006, Darmstadt, Germany

题意:用容量分别为C1和C2的两辆汽车搬运n个家具,第i个家具的体积为a[i],求出搬运完这n个家具所要的最少次数。

思路:有两辆汽车搬运家具,那么每一次搬运自然是需要选择合适的家具组合能让汽车装的下来。家具最多只有十个,我们如何选择合适的家具装到汽车里呢?我们可以通过状态压缩来解决,通过把n个家具转化为一个二进制数,1表示选择0表示不选择。初始化遍历所有的可能找到能够由两辆汽车装下的状态。那么现在考虑的是怎么判断一个状态能够被两辆汽车装下,我们可以找出所有家具组合其体积之和小于容量C1,然后判断剩余家具是否小于C2,如果满足那么这个状态就是我们要找到。

接下来就是01背包了,把我们之前挑选出来的能够被两辆汽车运走的家具组合当做物品,物品价值为1(求最小搬运次数,搬运一次次数加一)。我们要求的是所有家具被运走,并且是通过一个二进制数来表示那些家具被运走了,比如有五件家具,dp[10011]表示的就是运走第一件、第四件、第五件家具最少的次数。那么我们要找的也就是dp[11111]了,这里要注意家具只能被运一次,那么在用01背包逆序枚举容量的时候要判断一下,代码上有注释。此外一点就是01背包的状态转移方程一般是dp[j]=min(dp[j],dp[j-w[i]]+d[i]),但是我们的j是二进制数,不好用减法,我们可以转换一下,通过“|”来表示加法,那么状态转移方程就是dp[j|state[i]]=min(dp[j|state[i]],dp[j]+1)。

#include
#include
#include
#include
#include
using namespace std;
const int inf=999999999;
int dp[(1<<10)+5];
int state[(1<<10)+5];
int vis[105],a[15];
int c1,c2,v,n,tot;
int check(int x)
{
    memset(vis,0,sizeof(vis));
    int sum=0;
    vis[0]=1;
    for(int i=0;i>i)&1)
        {
            sum+=a[i];
            //这个循环就是找出容量和小于容量c1的家具组合 乍一看似乎有些不明白
            //自己在脑海或者是用纸笔模拟一遍就明白了,很巧妙的一个方法
            for(int j=c1;j>=a[i];j--)
            {
                if(vis[j-a[i]])
                    vis[j]=1;
            }
        }
    }
    if(c1+c2=0;j--)
            {
                if((state[i]&j)==0)//每个家具只能运一次,那么肯定每一位不能重复出现1,通过位运算判断是否重复
                    dp[j|state[i]]=min(dp[j|state[i]],dp[j]+1);
            }
        }
        printf("Scenario #%d:\n%d\n\n",++kase,dp[v]);
    }
    return 0;
}

你可能感兴趣的:(背包dp)