POJ-1276-Cash-Machine 二进制优化多重背包问题

来源:互联网 发布:如何注册淘宝卖家 编辑:程序博客网 时间:2024/05/18 01:00

一道多重背包的问题,但是常规解法亲测超时,无优化TLE

通过二进制化化为 01 背包,将 O(V*N) 降为 O(V*logN)

79MS AC


传送门:POJ-1276-Cash-Machine

#include <string.h>#include <stdio.h>#include <algorithm>int s,n,max,a[111],x,y,z,i,k,j,dp[100005];int main() {    while (scanf("%d", &s) != EOF) {        z = 0;        scanf("%d",&n);        for (i = 0; i < n; i++) {            scanf("%d%d", &x, &y);            k = 1; // 从 2^0开始            // 2进制优化转01背包            while (x>0) {                if(x>=k) {                    a[z++] = k*y;                    x -= k;                    k = k<<1;  // *2                }                else {                    a[z++] = x*y;                    break;                }            }        }        memset(dp, 0, sizeof(dp));        for(i=0; i<z; i++)            for(j=s; j>=a[i]; j--)                dp[j] = std::max(dp[j],dp[j-a[i]]+a[i]);        printf("%d\n",dp[s]);    }    return 0;}

附常规解法:


#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;int main(){    int cash,N,bill[12],me[12],dp[100001],i,j,k;    while(scanf("%d",&cash) != EOF) {        scanf("%d",&N);        if(cash == 0 || N == 0) {            printf("0\n");            continue;        }        for(i=0; i<N; i++)            scanf("%d%d", bill+i, me+i);        memset(dp, 0 ,sizeof(dp));        for(i=0; i<N; i++) {            for(j=cash; j>=me[i]; j--) {                for(k=1; k<=bill[i]; k++) {                    if(j < k*me[i])                        break;                    dp[j] = max(dp[j-k*me[i]]+k*me[i],dp[j]);                }            }        }        printf("%d\n",dp[cash]);    }    return 0;}
1 0