Relocation
链接: POJ - 2923
题目大意: 给你两辆车,每辆车有额定载重c1,c2,再给你n件物品(n<=10)的重量wi,每次都用两辆车往返运输,求最小的次数.
思路:看到n的数量很小,先想到暴力,可以枚举每次装车的情况,判断是否成立.先对装车的情况进行状态压缩,0代表不装,1为装,对状态进行暴力枚举.然后很容易想到用01背包进行判断方案是否可行,判断过程如下:先计算所选物品重量的总和,然后以c1车的容量进行01背包求能装下的最大重量,若 c2车的重量>总重量-c1车能装的最大重量则返回true代表可行.接着对物品的状态进行dp,将状态0转移到状态(1<
dp[i|sta[j]]=min(dp[i|sta[j]],dp[i]+1);
sta[j]为枚举的装车方案,i|sta[j]为装车后的装状态.
代码:
1 #include2 #include <string.h> 3 #include 4 #include 5 #include 6 #define INF 0x3f3f3f3f 7 #define MAXN 100000 8 using namespace std; 9 typedef long long ll; 10 int f[105],dp[1<<12],w[MAXN],sta[MAXN],c1,c2,n; 11 bool check(int st) 12 { 13 memset(f,0,sizeof(f)); 14 int sum=0; 15 for(int i=0;i ) 16 { 17 if(st&(1<<i)) 18 { 19 sum+=w[i]; 20 if(sum>c1+c2)continue; 21 for(int j=c1;j>=w[i];j--) 22 f[j]=max(f[j],f[j-w[i]]+w[i]); 23 } 24 } 25 if(c2>=sum-f[c1])return true; 26 return false; 27 } 28 int main() 29 { 30 ios::sync_with_stdio(false); 31 int cas; 32 cin>>cas; 33 for(int ca=1; ca<=cas; ca++) 34 { 35 memset(dp,INF,sizeof(dp)); 36 dp[0]=0; 37 cin>>n>>c1>>c2; 38 c1 > c2 ? c1 ^= (c2 ^= (c1 ^= c2)) : 0; 39 for(int i=0;i ) 40 cin>>w[i]; 41 int cnt=0; 42 for(int i=0;i<(1< ) 43 if(check(i))sta[cnt++]=i; 44 for(int i=0;i<(1< ) 45 { 46 for(int j=0;j ) 47 dp[i|sta[j]]=min(dp[i|sta[j]],dp[i]+1); 48 } 49 cout<<"Scenario #"< ":"<<endl; 50 cout< 1< 1]<<endl; 51 if(ca endl; 52 } 53 return 0; 54 }