题解 P5020 【货币系统】
唔。。本蒟蒻在考场上以为这题又是【大凯的疑惑】这样的数竞题,果断放弃。出了考场神犇说这是完全背包。本蒟蒻就回来敲敲打打搞出了这个luogu数据95分的代码。
基本思路
首先,请看这道完全背包模板题【P1616】疯狂的采药。 将钱数从小到大排好序,然后从后往前枚举,检查这个面额是否能被更小的面额表示出来。如果可以,将该面额去掉。 可以把要表示的大面额看成【背包容量】,把小面额看成【单个物品的重量】。也就成了【完全背包】。
由于这题数据不太大,所以直接枚举貌似可以过大部分。
关键代码如下
for(int i=n;i>=1;i--)
{
memset(f,0,sizeof(f));
for(int o=1;o<i;o++)
for(int p=a[o];p<=a[i];p++)
f[p]=max(f[p-a[o]]+a[o],f[p]);
if(f[a[i]]==a[i])ans--;
}
代码呈现
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int a[105],f[25005],t,n,ans;
int main()
{
cin>>t;
for(int i=1;i<=t;i++)
{
memset(f,0,sizeof(f));
memset(a,0,sizeof(a));
cin>>n;
ans=n;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1);
for(int i=n;i>=1;i--)
{
memset(f,0,sizeof(f));
for(int o=1;o<i;o++)
for(int p=a[o];p<=a[i];p++)
f[p]=max(f[p-a[o]]+a[o],f[p]);
if(f[a[i]]==a[i])ans--;
}
cout<<ans<<endl;
}
return 0;
}