这题是完全背包问题,求方案数
重点:i,j都代表钱数,i代表序号也代表钱数
如果改成只有一分钱三分钱五分钱,则需要一个数组a[i]存几分钱,然后dp[j] = max(dp[j], dp[j] + dp[j-a[i]]);
#include<iostream>
using namespace std;
int dp[32769];
int main()
{
dp[0]=1;
for(int i=1; i<=3; i++)
for(int j=1; j<=32768; j++)
dp[j] = max(dp[j], dp[j] + dp[j-i]);
int n;
while(cin>>n)
{
cout<<dp[n]<<endl;
}
return 0;
}
牛客 能量水晶
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e3+5;
int n,m,ans;
int a[N],sum[N],f[N];
signed main(){
scanf("%lld%lld",&n,&m);
for (register int i=1; i<=n; ++i) scanf("%lld",&a[i]);
sort(a+1,a+n+1);
for (register int i=1; i<=n; ++i) sum[i]=sum[i-1]+a[i];
f[0]=1;
for (register int i=n; i>=1; --i)
{
if (sum[i-1]<=m)
for (register int j=max(0ll,m-sum[i]+1); j<=m-sum[i-1]; ++j) ans+=f[j];
//当最小的不选的数为6时,我们发现,只要再在[3,8]内选任意魔法即可
//后面至少要选总大小为 max(0,m-sum[i]+1)的魔法数,不然6就可以被选进去了
//这个区间取的很巧在,这个区间任选一个后就不可能在选到a[i]这个数
//后面最多能选的魔法数为:m-sum[i-1],即还剩下的空间
for (register int j=m; j>=a[i]; --j) f[j]+=f[j-a[i]];
//01计数背包,记得f[0]==1;
}
printf("%lld\n",ans);
return 0;
}