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:
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 n, C1 and C2. C1 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
这道题是用状态压缩+01背包,因为物品只有10件,所以会想到状压dp,先把所有的物品都用0和1表示,0表示物品还没有被搬走,1表示已经被搬走,用dp[state]记录从所有物品都未被搬走到状态state所要搬的最少次数。可以先算出哪些状态是一次就能搬走的,这里要用到01背包的思想,先看看该状态下c1可以容纳多少重量,然后用看看把这些重量搬走后剩下的质量能不能被c2所容纳。这些都处理完后,就用状态转移方程dp[j|state]=min(dp[j|state,dp[state]+1},这个方程很巧妙啊,开始还以为是两个能一次搬走的状态结合,其实是利用能一次搬走,所以在之前的基础上加上这个一次能搬走的状态。最后的结果就是dp[1<<(n-1)]啦。
#include<stdio.h> #include<string.h> #define inf 88888888 int c1,c2,n,w[15],state,yici[1500],vis[150],dp[1500]; int min(int x,int y){ return x<y?x:y; } int panduan(int x) { int i,j,sum=0; memset(vis,0,sizeof(vis)); vis[0]=1; for(i=1;i<=n;i++){ if((1<<(i-1))&x){ sum+=w[i]; for(j=c1;j>=w[i];j--){ if(vis[j-w[i]]){ vis[j]++; } } } } if(sum>c1+c2)return 0; for(i=0;i<=c1;i++){ if(vis[i] && sum-i<=c2)return 1; } return 0; } int main() { int m,i,j,T,t,num1=0; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&c1,&c2); for(i=1;i<=n;i++){ scanf("%d",&w[i]); } t=0; memset(yici,0,sizeof(yici)); for(i=1;i<(1<<n);i++){ dp[i]=inf; if(panduan(i)){ yici[++t]=i; dp[i]=1; } } dp[0]=0; for(i=1;i<(1<<n);i++){ for(j=1;j<=t;j++){ if(yici[j]&i)continue; dp[i|yici[j]]=min(dp[i|yici[j]],dp[i]+1); } } num1++; printf("Scenario #%d:\n",num1); printf("%d\n\n",dp[(1<<n)-1]); } return 0; }
原文地址:http://blog.csdn.net/kirito_acmer/article/details/46606683