zoj 1149 || poj 1014 Dividing(多重背包)

 

其实吧,这题我是当水题来做的 = =。。WA之后。。。用DFS做了下,TLE了之后,发现这个不就是多重背包么 = =。。

 

给你6种大理石的value,每种给出数量,看能不能把总value给平均分开。也就是求背包sum/2里的值是不是等于sum/2。

 

开始的想法太水了,直接将每种的数都存到数组里 = =。。。然后从前往后加 = =。。看能不能加到sum/2。这个想法是错误的,因为sum/2的获得不一定是前面的数的加和。。。 然后就用DFS了,试了下 20000那组数据,出不来答案,侥幸交下,毫无疑问的TLE = =。。然后想起来背包了,= =。。我现在存的数直接用01背包就好。 = =。。可是捏,TLE了 = =。。好吧,按二进制拆分,交了,过了 = =。。。120MS。。

 

然后先算sum判断不是奇数后再拆分,10ms过了~~

 

好久没做背包的题了,那俩循环都忘了 = =。。。回顾下。。。

 

#include <cstdio> #include <cstdlib> #include <iostream> #include <string.h> #define MAX 300010 using namespace std; int num[MAX]; int cou,sum; void add(int k,int n) //多重背包的二进制拆分 { int i,x,tmp = 0; for(i=0; ; i++) { x = 1<<i; if( tmp + x > k ) break; tmp += x; num[cou++] = x*n; } x = k - tmp; if( x != 0 ) num[cou++] = n*x; } int flag,bag[MAX]; int DP() // 01背包。 { int i,k; for(i=0; i<cou; i++) for(k=sum; k>=num[i]; k--) if( bag[k-num[i]] + num[i] > bag[k] ) bag[k] = bag[k-num[i]] + num[i]; return bag[sum] == sum ; } int main() { int a,b,c,d,e,f,i; int ind = 1; while( scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f) != EOF ) { sum = cou = 0; if( !( a || b || c || d || e || f ) ) break; sum += a*1; sum += b*2; sum += c*3; sum += d*4; sum += e*5; sum += f*6; printf("Collection #%d:/n",ind++); if( sum % 2 == 1 ) { printf("Can't be divided./n/n"); continue; } add(a,1); add(b,2); add(c,3); add(d,4); add(e,5); add(f,6); sum /= 2; memset(bag,0,sizeof(bag)); flag = DP(); if( flag ) printf("Can be divided./n/n"); else printf("Can't be divided./n/n"); } return 0; }  

你可能感兴趣的:(c)