题目大意:有个人需要搬家,有N件物品,给个物品的重量是 w[i] 然后又两个车,每个车的载重量分别是C1和C2,求最少需要运输多少次才能把这些物品全部运输完毕。
分析:刚开始就发现物品数不多,想着直接先枚举一辆车运输的物品,然后计算它运输这些物品需要多少次,不过后来发现复杂度有点高,另一种比较好的解法是先枚举两个车一次可以运走的物品,然后再去用这些可以运走的状态去相互匹配转移,dp[i]表示达到状态i最少的运输次数,求是否能一次运输某个状态也是简单的01背包问题。
代码如下:
=======================================================================================================================
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> using namespace std; const int MAXN = 1<<10; const int Bit = 10; const int oo = 1e9+7; int N, Ca, Cb; bool Judge(int x, int w[]) {///判断状态为x的时候是否能一次运输完毕 int v[107]={1}, sum=0; for(int i=0; i<N; i++)if(x & (1<<i)) { sum += w[i]; for(int j=Ca-w[i]; j>=0; j--) { if(v[j])v[j+w[i]] = true; } } if(sum > Ca+Cb)return false; for(int i=0; i<=Ca; i++) { if(v[i] && Cb >= sum-i) return true; } return false; } int main() { int T, t=1; scanf("%d", &T); while(T--) { int i, j, M, w[MAXN], f[MAXN], k=0; scanf("%d%d%d", &N, &Ca, &Cb); for(i=0; i<N; i++) scanf("%d", &w[i]); for(i=0, M=1<<N; i<M; i++) { if(Judge(i, w))f[k++] = i; } int dp[MAXN]={0}; for(i=1; i<M; i++) dp[i] = oo; for(i=0; i<k; i++) for(j=0; j<M; j++) { if((j&f[i]) == 0) { dp[j|f[i]] = min(dp[j|f[i]], dp[j]+1); } } printf("Scenario #%d: %d ", t++, dp[M-1]); } return 0; }