這道題目是一個多重背包的題目,多重背包實際上就是把整個物品的件數拆分成a0?20+a1?21+a2?22+...an?2n且a=0或1這樣每一次最優解實際上就是在之前的基礎上進行的最優解的累加,但是發現如果物品數量不是恰好是某幾個數之和,那么就會出現有幾個統計不到的情況,那么只要提出來單獨處理這多出來的件數的背包就好了。還有一點需要注意的就是背包的時候要倒著枚舉因為是1維數組,那么如果修改了當前的值那么當前的值就會被覆蓋,那么更新這個背包的時候就可能用到當前這個背包的值,所以顯然不能這么干。
核心代碼:
while(k <= num){end = k*c;for(int V=m;V>=end;V--)f[V] = max(f[V], f[V-k*c]+wei*k);num -= k;k *= 2;}if(num > 0){end = num*c;for(int V=m;V>=end;V--)f[V] = max(f[V], f[V-num*c]+wei*num);}
這道題太裸了,主要是練習一下。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1000;
const int MAXM = 1000;
int n, m;
int wei, c, num, f[MAXM+10];
int main(){int C;scanf("%d", &C);while(C--){memset(f, 0, sizeof f);scanf("%d%d", &m, &n);for(int i=1;i<=n;i++){scanf("%d %d %d", &c, &wei, &num);int k=1, end;if(num*c > m)num = m / c;while(k <= num){end = k*c;for(int V=m;V>=end;V--)f[V] = max(f[V], f[V-k*c]+wei*k);num -= k;k *= 2;}if(num > 0){end = num*c;for(int V=m;V>=end;V--)f[V] = max(f[V], f[V-num*c]+wei*num);}}printf("%d\n", f[m]);}return 0;
}