题意很简单, 有n种硬币,每种硬币面额多大,有多少个,求可以构成m以内的面额有多少种。
开始用的是普通的多重背包的求法,裸裸的超时了,看了别人的代码,发现可以优化很多。
用usea这个来存储用来多少个a硬币,避免的很多无用的计算。
先贴以前超时的代码
#include <stdio.h>
#include <string.h>
int dp[100005];
int coin[101];
int cnt[101];
int used[1000101];
int main()
{
int n, k;
while(scanf("%d %d", &n, &k))
{
if (n==0 && k==0)
break;
for (int i = 1; i <= n; i++)
{
scanf("%d", &coin[i]);
}
for (int j = 1; j <= n; j++)
{
scanf("%d", &cnt[j]);
}
memset(dp, 0, sizeof(dp));
dp[0] = 1;
int ans = 0;
for (int i = 1; i <= n; i++)
{
memset(used, 0, sizeof(used));
for (int j = coin[i]; j <= k; j++)
{
if (!dp[j] && dp[j-coin[i]] && used[j-coin[i]] < cnt[i])
{
ans++;
used[j]=used[j-coin[i]]+1;
dp[j] = 1;
}
}
}
printf("%d\n", ans);
}
return 0;
}
下面是A了的代码
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
int a[105];
int c[105];
bool canpay[100005];
int usea[100005];
int main()
{
int n, m;
while (scanf("%d %d", &n, &m) && (m||n))
{
memset(canpay, 0, sizeof(canpay));
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++)
scanf("%d", &c[i]);
int ans = 0;
canpay[0] = true;
for (int i = 1; i <= n; i++)
{
memset(usea, 0, sizeof(usea));
for (int j = a[i]; j <= m; j++)
{
if (!canpay[j] && canpay[j-a[i]] && usea[j - a[i]] < c[i])
{
ans += 1;
canpay[j] = true;
usea[j] = usea[j - a[i]] + 1;
}
}
}
printf("%d\n", ans);
}
return 0;
}