POJ 1276 Cash Machine

解题思路:dp(多重背包问题)

将多重背包转化为01背包,假设每个物品的数量上限为n,每件的体积为0,价值为w

那么可以把该物品分为1,2,4,...,2^(k-1)和n-(2^k+1),那么新的物品就是(体积,价值):(0,w),(0,2w),...,(0,2^(k-1)w)和(0,(n-2^k+1)w)

(这样可以构造出任何<=n的情况,假设n为7,则分成系数为1,2和4,那么1-7的所有情况均可由1,2,4这3个基数组合得到)

NULL
   
     
#include < iostream >
using namespace std;
#define MAXN 100001
int main()
{
int c,m,i,j,k,t,p;
int d[ 11 ],n[ 11 ],dp[MAXN];
while (scanf( " %d %d " , & c, & m) != EOF)
{
for (i = 0 ;i < m;i ++ )scanf( " %d %d " , & n[i], & d[i]);
memset(dp,
0 , sizeof (dp));
for (i = 0 ;i < m;i ++ )
if (n[i] * d[i] == c){dp[c] = c; break ;}
else if (n[i] * d[i] > c)
{
for (j = d[i];j <= c;j ++ )
if (dp[j - d[i]] + d[i] > dp[j])dp[j] = dp[j - d[i]] + d[i];
}
else
{
for (t = n[i],j = 1 ;j <= (n[i] >> 1 );t -= j,j *= 2 )
for (k = c,p = j * d[i];k >= p;k -- )
if (dp[k - p] + p > dp[k])dp[k] = dp[k - p] + p;
for (k = c,p = t * d[i];k >= p;k -- )
if (dp[k - p] + p > dp[k])dp[k] = dp[k - p] + p;
}
printf(
" %d\n " ,dp[c]);
}
return 0 ;
}

 

你可能感兴趣的:(mac)