Multiple backpack + binary split POJ1014

The meaning of problems: the right values ​​of 1,2,3,4,5,6 marble, each with several blocks, 2 parts can put them into equal weights. The total number of marble does not exceed 20,000. (Multiple backpack)

Analysis: judge dp [V / 2] == V / 2 can be, but the process will time out if ordinary practices that make multiple backpack as 01 backpack inefficient, this time to use the binary split optimization, the complexity of change for image.png

Binary split Principle:image.png

image.png

Here means a large number 11101111, as long as we have a number 1 on each one, can be represented by the large number is 1248 (1101001000 ..) may be expressed in any number, then any number can go through a binary number into a process, for the convenience of each binary number is only one, this process can be seen as divided into the 13 1,2,4,6 (last 6 easy to handle avoid duplication).

 

Binary split:

for ( int I = . 1 ; I <= n-; I ++ ) 
{ 
    for ( int J = . 1 ; J <[I] = NUM; J = << . 1 )
     // binary each enumeration.
     // NOTE young age to large split 
    { 
        NUM [I] - = J; // subtracting spun off 
        new_c [TOT ++] = J * C [I]; // synthesis of a large volume of articles 
        new_w [tot] = j W * [I]; // synthesis of a large value of the thing 
    }
     iF (NUM [I]) // . the remainder of determining whether there
     // if we have a certain item 13, as clearly split into binary 1,2,4.
     // we have more than 6 out of part of, so they need another serving. 
    { 
        new_c [tot ++] = num [i] * c [i]; 
        new_w [tot] = num [i] * x [i]; 
        num [i] = 0 ; 
    } 
}
View Code

Code:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;

const int maxn=120012;
int n,V;
int dp[maxn];
int a[7];
int v[maxn],w[maxn];
int main(){
    int kase=1;
    while(scanf("%d %d %d %d %d %d",&a[1],&a[2],&a[3],&a[4],&a[5],&a[6])!=EOF){
        if(a[1]==0&&a[2]==0&&a[3]==0&&a[4]==0&&a[5]==0&&a[6]==0) break;
        memset(dp,0,sizeof(dp));
        printf("Collection #%d:\n",kase++);
        V=n=0;
        for(int i=1;i<=6;i++){
            V+=a[i]*i;
        }
        if(V&1){
            printf("Can't be divided.\n\n");
            continue;
        }
        else{            
            int tot=0;
            for(int i=1;i<=6;i++){
                for(int j=1;j<=a[i];j<<=1){
                    a[i]-=j;
//                    printf("a[i]=%d j=%d\n",a[i],j);
                    w[tot]=j*i;
                    v[tot++]=j*i;
                }
                if(a[i]!=0){
                    v[tot]=a[i]*i;
                    w[tot++]=a[i]*i;
                }
            }
//            printf("tot=%d\n",tot);
            for(int i=0;i<tot;i++){
                for(int j=V/2;j>=w[i];j--){
                    dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
                }
            }
//            for(int i=6;i>=1;i--){
//                for(int k=v/2;k>=i;k--){
//                    for(int j=1;j<=a[i];j++){
//                        if(k-i*j>=0)
//                            dp[k]=max(dp[k],dp[k-i*j]+i*j);
//                        
////                        printf("dp[k]=%d\n",dp[k]);
//                    }
//                }
//            }    
            if(dp[V/2]==V/2)
                printf("Can be divided.\n\n");
            else
                printf("Can't be divided.\n\n");
        }
    }
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/-Zzz-/p/11415834.html