poj 2392 Space Elevator(多重揹包)
阿新 • • 發佈:2019-02-17
題意:
k種石頭(不用在意具體是什麼東西),每種石頭的高度為h,這種石頭不能處於超過a的高度,數量為c,問最多能用這些石頭疊出多大的高度
解題思路:
這是一道稍微有點改動的多重揹包題目,被改為每種石頭都有一個容量限制。
多重揹包的問題我們可以進行轉換,對於c*h>=a的石頭,在不超過a的條件下,無論去多少塊石頭都不會用完c,所以就是可以轉換為完全揹包問題,
而c*h<a的石頭,就是c個(價值為h,2*h,....c*h)的01揹包問題了,這裡可以用二進位制加速一下。因為有轉換成二進位制數後能表示出1到c的所有數,所以效果一樣。
程式碼:
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int maxn=40000; struct p { int a; int h; int c; }x[505]; bool cmp(p a, p b) { return a.a<b.a; } int f[maxn+5]; void complete(int x, int y) { int i; for(i=x; i<=y; i++) { if(f[i-x])f[i]=1; } return; } void ZeroPack(int x, int y, int z) { for(int i=z; i>=x; i--) { if(f[i-x]) { f[i]=1; } } return; } int main() { int k; cin>>k; int i, j; for(i=0; i<k; i++) { scanf("%d%d%d", &x[i].h, &x[i].a, &x[i].c); } sort(x, x+k, cmp); f[0]=1; for(i=0; i<k; i++) { if(x[i].c*x[i].h>=x[i].a) { complete(x[i].h, x[i].a); } else { int e=1; for(j=x[i].c; j>e; ) { ZeroPack(e*x[i].h, e, x[i].a); j-=e; e<<=1; } ZeroPack(j*x[i].h, j, x[i].a); } } for(j=maxn; j>0; j--) { if(f[j])break; } // for(; j>0; j--)printf("%d\n", f[j]); printf("%d\n", j); }