click here~~
題意:
有價值為1~6的珠寶,每種價值的珠寶數量已經給出,問是否可以將價值平分。
解題思路:
又是一道平分問題,於是可以將問題轉化為容量為 sum/2 的揹包問題(sum為總價值)。
對於每種價值的物品 i ,是乙個費用為 i ,價值為 i ,數量為num[i]的多重揹包。
還用到了多重揹包常用的二進位制優化。
方法是:將第 i 種物品分成若干件物品替換以後的物品,其中,每件物品有乙個係數,這件物品的費用和價值均是原來的費用和價值乘以這個係數。
我們使這些係數分別為1,2,4,…,2^(k-1),num[i]-2^k+1,且k是滿足num[i]-2^k+1>0的最大整數。
比如,num[i]為14,就將這種物品分為係數為1,2,4,7的四件物品。
如此,複雜度為o(n*∑log num[i]),優化了很多。
**很好實現。下面是我寫的,不算精簡。
#include #include #include using namespace std;
#define clr(a,v) memset(a,v,sizeof(a))
int num[7],dp[60010];
int dig=;
int main()
if(sum == 0)
break;
printf("collection #%d:\n",++ncase);
if(sum&1)
clr(dp,0);
sum /= 2;
for(int i=1;i<=6;i++)
else
for(int j=sum;j>=v;j--)
dp[j] = max(dp[j],dp[j-v]+v);}}
if(dp[sum] == sum)
printf("can be divided.\n\n");
else
printf("can't be divided.\n\n");
}return 0;
}
從風神部落格中抄了個模板,挺清楚的。
#include #include #define n 60006
#define max(a,b) a > b ? a : b
int v,num[7],dp[n];
void bag_01(int c,int w)
void bag_all(int c,int w)
void bag_multiple(int c,int w,int num)
int k = 1;
while(k < num)
bag_01(c*num,w*num);
}int main()
if(sum == 0)
break;
printf("collection #%d:\n",++ncase);
if(sum&1)
memset(dp,0,sizeof(dp));
v = sum/2;
for(int i=1;i<=6;i++)
bag_multiple(i,i,num[i]);
if(dp[v] == v)
printf("can be divided.\n\n");
else
printf("can't be divided.\n\n");
}return 0;
}
hdu1059 Dividing 多重揹包
題意 將價值分別為1,2,3,4,5,6的6種多個物品平均分兩坨 所有物品數量加起來不超過2w個 很容易想到dp的思路,dp i 表示是否存在使價值為i的選法,dp i dp i j j為物品的價值。然後對所有物品進行這種迴圈即可,但是會超時,這時候就需要將大量的相同物品二進位制分割,具體的原理需要...
HDU 1059 Dividing(多重揹包)
題意 輸入6個數字,表示重量分別為1 2 3 4 5 6的大理石的數量 問能不能將這些大理石均分,不能把大理石弄破了 能的話就輸出 can be divided.不能就輸出can t be divided.解題思路 邊輸入邊求和 如果和為0,就break 如果和為奇數,就輸出can t be div...
HDU 1059 Dividing 多重揹包
題目就是要分彈珠,一人一半,多乙個少乙個都不行。六種彈珠,ni表示價值i的彈珠的數量,問能不能分。1.總價值為奇數當然不能分了。2.總價值為偶數,利用多重揹包求解,揹包容量為m 2,計算dp m 能否等於m,能就可以分。include includeint val 10 num 10 int dp ...