题意:有一个钞票机,里面有N种面额的钞票d1,d2...dn各n1,n2...n3,如果我要cash元,问它最多能给吐我多少钱(它吐出的钱数不会大于我的需求)。
思路:多重背包。但在一开始的时候只是简单地加一个循环,然后
for(int i = 0; i < N; i++)
for(int j = 0; j <= n[i]; j++)
for(int k = 0; k <= cash; k++)
dp[k] = max(dp[k], dp[k - j * d[i]] + j * d[i]);
TLE,因为n[i]可以很大,而可以利用二进制转化将它的规模变小
#include
#include
#include
int ans[100010];
int d[300];
int main()
{
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
int cash, N, cur,count;
int a, b;
while(scanf("%d%d", &cash, &N) != EOF)
{
count = 0;
for(int i = 0; i < N; i++)
{//读入钞票数量和面值的同时进行二进制转换
scanf("%d%d", &a, &b);
for(int j = 1; j <= a; j *= 2 )
{
d[count++] = b * j;
a -= j;
}
if(a > 0)
d[count++] = b * a;
//相当于得到不同面值的钞票各一张,可从它们中任取一些组成n*b(1<=n<=a)
}
memset(ans, 0, sizeof(ans));
for(int i = 0; i < count; i++)
{//转化为01背包问题求解
for(int j = cash; j >= d[i]; j--)
{
cur = ans[j - d[i]] + d[i];
if(cur >= ans[j])
{
ans[j] = cur;
}
}
}
printf("%d\n", ans[cash]);
}
return 0;
}