POJ 1276 Cash Machine

        这是个多重背包问题。。

        可以把这个转化成01背包和完全背包的合体来做。做法是枚举每一件物品,如果发现在这件物品的数量乘以价格超过了cash,就可以把这个物品的数量当成无限来做,也就是完全背包。

        否则的话,就把这nk[i]件物品拆分成为多件物品,每件物品相对于原先的数量1 , 2 , 4 ,6 ,。。。。。。,2*k件,其中2*k <= nk[i]/2。1-nk[i]的数,都可以由这些数组合而成。于是01背包。

        也可以转化成完全背包来做,只需要用一个mem[j]数组记录在总价值为j时,当前物品的使用数量。如果等于或超过了nk[i],就不取了。

 

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int dp[100011],mem[100011];
int main()
{
    int cash,n,nk[12],dk[12],i,j,k;
    while (scanf("%d",&cash) != EOF)
    {
        scanf("%d",&n);
        for (i=1; i<=n; i++)
        {
            scanf("%d%d",nk+i,dk+i);
        }
        memset(dp,0,sizeof(dp));
        for (i=1;i<=n; i++)
        {
            memset(mem,0,sizeof(mem));
            for (j=1; j<=cash; j++)
            {
                if (j-dk[i] < 0)
                    continue;
                if (mem[j-dk[i]] < nk[i] && dp[j] < dp[j-dk[i]]+dk[i])
                {
                    dp[j]=dp[j-dk[i]]+dk[i];
                    mem[j]=mem[j-dk[i]]+1;
                }
            }
        }
        printf("%d\n",dp[cash]);
    }
}

你可能感兴趣的:(POJ 1276 Cash Machine)