很经典的多重背包问题,大家可以看看《背包九讲》里面的第三讲。
/******************************************************************************* # Author : Neo Fung # Email : [email protected] # Last modified: 2011-10-02 20:46 # Filename: ZOJ1149 POJ1014 HDU1059 Dividing.cpp # Description : ******************************************************************************/ // #include "stdafx.h" // #define DEBUG #include <fstream> #include <stdio.h> #include <iostream> #include <string.h> #include <string> #include <memory.h> using namespace std; int dp[450000],value[200000]; int main(void) { #ifdef DEBUG freopen("data.txt","r",stdin); #endif int ind=1; int num[7]; while(scanf("%d %d %d %d %d %d",&num[1],&num[2],&num[3],&num[4],&num[5],&num[6])!=EOF) { int total=0; for(int i=1;i<=6;++i) total+=i*num[i]; if(total==0) break; printf("Collection #%d:\n",ind++); if(total%2) { printf("Can't be divided.\n\n"); continue; } int half=total/2; int ncount=0; memset(dp,0,sizeof(dp)); for(int i=1;i<=6;++i) //二进制拆分 { int temp=num[i]; if(temp==0) continue; int pow2=1; while(temp>pow2) { value[ncount++]=pow2*i; temp-=pow2; pow2*=2; } if(temp) value[ncount++]=temp*i; } for(int i=0;i<ncount;++i) //转变为0/1背包问题 for(int j=half;j>=value[i];--j) dp[j]=max(dp[j],dp[j-value[i]]+value[i]); if(dp[half]==half) printf("Can be divided.\n\n"); else printf("Can't be divided.\n\n"); } return 0; }