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

    xiaoxiao2021-03-25  118

            多重背包的要求,是分别给出不同物品的最大数量。

            其实多重背包最简单的做法就是将一种数量为n的的物品看作n件不同的物品,从而使用01背包,也就是在01背包的基础上,再加一个for循环,但是其算法复杂度较高,因此我们会运用二进制分解优化算法。

            首先,要知道一句话,把一个数c分解成若干个小于等于c的数的集合,这个集合中的数任意相加可以得到所有小于等于c的数。这句话是我自己想的,看起来像句废话。还是看例子吧,例:15,二进制,1111,把它分解成1000,0100,0010,0001即8,4,2,1。这四个数任意相加可以得到任意小于等与15的数。

            将所有物品的数量用二进制分解后,就将多重背包转化为了01背包问题,而且进一步优化了算法。

    Cash Machine Time Limit: 1000MS Memory Limit: 10000K

    Description

    A Bank plans to install a machine for cash withdrawal. The machine is able to deliver appropriate @ bills for a requested cash amount. The machine uses exactly N distinct bill denominations, say Dk, k=1,N, and for each denomination Dk the machine has a supply of nk bills. For example, N=3, n1=10, D1=100, n2=4, D2=50, n3=5, D3=10 means the machine has a supply of 10 bills of @100 each, 4 bills of @50 each, and 5 bills of @10 each. Call cash the requested amount of cash the machine should deliver and write a program that computes the maximum amount of cash less than or equal to cash that can be effectively delivered according to the available bill supply of the machine. Notes: @ is the symbol of the currency delivered by the machine. For instance, @ may stand for dollar, euro, pound etc.

    Input

    The program input is from standard input. Each data set in the input stands for a particular transaction and has the format: cash N n1 D1 n2 D2 ... nN DN where 0 <= cash <= 100000 is the amount of cash requested, 0 <=N <= 10 is the number of bill denominations and 0 <= nk <= 1000 is the number of available bills for the Dk denomination, 1 <= Dk <= 1000, k=1,N. White spaces can occur freely between the numbers in the input. The input data are correct.

    Output

    For each set of data the program prints the result to the standard output on a separate line as shown in the examples below.

    Sample Input

    735 3 4 125 6 5 3 350 633 4 500 30 6 100 1 5 0 1 735 0 0 3 10 100 10 50 10 10

    Sample Output

    735 630 0 0

    代码

    #include <iostream> #include <cstdio> #include <cstring> using namespace std; int dp[100005], val[100005]; int max(int a,int b) { if (a>b) return a; else return b; } int main() { int M, N; int i, j; while (scanf("%d %d",&M,&N) != EOF) { int n, v, cnt=0; memset(dp, 0, sizeof(dp)); memset(val, 0, sizeof(val)); for (i=1; i<=N; ++i) { scanf ("%d %d",&n,&v); for (j=1; j<=n; j<<=1) //二进制优化 { val[cnt++] = j*v; n-=j; } if (n>0) val[cnt++] = n*v; } for (i=0; i<cnt; i++) for (j=M; j>=val[i]; j--) dp[j] = max(dp[j], dp[j-val[i]]+val[i]); printf ("%d\n",dp[M]); } return 0; }

    转载请注明原文地址: https://ju.6miu.com/read-15962.html

    最新回复(0)