In the multi-resolution backpack direct method, the number of $ c [i] $ object dismantled into $ c [i] $ different objects
This makes a lot more types of objects, making the low efficiency of the algorithm.
The above-described method $ c [i] is split into $ $ c [i] a $ 1, may be arbitrarily selected so expressed between $ $ $ 1 to $ c [i] all numbers, so as to achieve multiple purposes backpack
I thought, from $ 2 ^ 0,2 ^ 1,2 ^ 2, ..., 2 ^ k $ arbitrarily selected to be shown $ 1 $ $ 2 ^ {k + 1} $ all numbers between -1
So there will be a binary split method :
First, find the maximum of $ k $, such that $ \ sum_ {i = 0} ^ {k} 2 ^ i <= c [i] $
Order $ t = \ sum_ {i = 0} ^ {k} 2 ^ i $, easy to know, above $ k + 1 $ the number may be composed of any number between $ 1 and $ T $ $
That $ t + 1 $ to $ c [i] how the number between $ express it?
Order $ p = c [i] -t $, then split a p, can, for the following reasons:
$ C [i] = p + t, c [i] -1 = p + t-1 ... $ and so on
Since the $ 1 to $ $ t $ has been expressed, so this way $ 1 to $ $ c [i] are each an integer of between $ may be expressed
Specifically, it is the number of $ c [i] $ object into a $ k + 2 $, their volumes were $ 2 ^ 0 * v [i], 2 ^ 1 * v [i], .. ., 2 ^ k * v [i], p $
Code:
Is $ POJ1742Coins $ code, although it will TLE, when it split method called binary pair of board
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define Ri register int 5 #define il inline 6 #define mem(a,b) memset(a,b,sizeof(a)) 7 #define go(i,a,b) for(Ri i=a;i<=b;i++) 8 #define yes(i,a,b) for(Ri i=a;i>=b;i--) 9 using namespace std; 10 const int N=101,M=100001; 11 int n,m,t,p,ans,a[N],c[N]; 12 bool f[M]; 13 il void calc(int x) 14 { 15 t=1,p=0; 16 while(t<=x){t+=(t<<1);p++;} 17 t=x-t/3;p--; 18 } 19 int main() 20 { 21 while(scanf("%d%d",&n,&m)&&n) 22 { 23 mem(f,0);ans=0; 24 go(i,1,n)scanf("%d",&a[i]); 25 go(i,1,n)scanf("%d",&c[i]); 26 f[0]=1; 27 go(i,1,n) 28 { 29 calc(c[i]); 30 go(j,0,p) 31 { 32 int q=1;if(j)q*=2; 33 yes(k,m,a[i]*q) 34 f[k]|=f[k-a[i]*q]; 35 } 36 yes(k,m,t)f[k]|=f[k-t]; 37 } 38 go(i,1,m)if(f[i])ans++; 39 printf("%d\n",ans); 40 } 41 return 0; 42 }