標籤:blog 使用 2014 art 問題 cti
這道題使用多重背包,不過其實我也不太明白為什麼叫這個名字。
因為感覺不是什麼多重,而是物體的分解問題。
就是比如一個物體有數量限制,比如是13,那麼就需要把這個物體分解為1, 2, 4, 6
如果這個物體有數量為25,那麼就分解為1, 2, 4, 8, 10
看出規律嗎,就是分成2的倍數加上位元,比如6 = 13 - 1 - 2 - 4, 10 = 25 - 1 - 2 - 4 - 8,呵呵,為什麼這麼分解?
因為這樣分解之後就可以組合成所有1到13的數,為25的時候可以組合成所有1到25的數啦。
就是這麼一個分解物體,最後組合的問題,叫成什麼多重背包罷了。
不明白?
給多幾個數字組合:
31分解 1, 2, 4, 8, 16
32分解1,2,4, 8, 16, 1
33分解1,2,4,8,16,2
如此分解的。
想通了,其實一點難度都沒有,和一般背包問題一樣做法了。
#include <stdio.h>#include <vector>using std::vector;const int SIZE = 7;int N[SIZE];bool findPartition(){int sum = 0;for (int i = 1; i < SIZE; i++)sum += i * N[i];if (sum & 1) return false;int half = sum >> 1;vector<bool> part(half+1);part[0] = true;for (int i = 1; i < SIZE; i++){int k = 1;for ( ; (k<<1) <= N[i]; k <<= 1){//例:13分解為1,2,4,6可以組合為1到13個物品,故此考慮了所有情況了for (int j = half; j >= k*i; j--){if (part[j-k*i]) part[j] = true;}}k = N[i] - k + 1;for (int j = half; j >= k*i; j--){if (part[j-k*i]) part[j] = true;}}return part[half];}int main(){int t = 1;while (true){int val = 0;for (int i = 1; i < SIZE; i++){scanf("%d", &N[i]);val += N[i];}if (!val) return 0;if (findPartition()) printf("Collection #%d:\nCan be divided.\n\n", t++);else printf("Collection #%d:\nCan't be divided.\n\n", t++);}return 0;}