HDU 1059 Dividing 多重揹包

2021-08-27 01:41:05 字數 1780 閱讀 9074

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 ...