题目链接:https://www.luogu.org/problemnew/show/P1164
思路:可用动态规划解决,对于每个a[i]有选和不选两种情况,用dp(i,j)代表到当前第i层背包容量(可以装的钱数)为j时可能的情况数,由此写出状态转移方程:dp(i,j)=dp(i-1,j)(上一层背包容量为j时的情况数,也就是不选菜品a[i]的情况数)+dp(i-1,j-a[i]) (上一层背包容量为j-a[i]的情况数,也就是本层选择菜品a[i]的情况数)
c++代码:
#include <iostream>
#include <cstring>
using namespace std;
const int maxn=1005;
int dp[105][maxn];
int a[105];
int main() {
int n,m;
cin >> n >> m;
for(int i=1;i<=n;i++)
cin >> a[i];
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++) {
for(int j=0;j<=m;j++) {
if(j==a[i])dp[i][j]=dp[i-1][j]+1;
else if(j>a[i])dp[i][j]=dp[i-1][j]+dp[i-1][j-a[i]];
else if(j<a[i])dp[i][j]=dp[i-1][j];
}
}
cout <<dp[n][m] << endl;
return 0;
}
滑动数组优化空间:
#include <iostream>
#include <cstring>
using namespace std;
const int maxn=1005;
int dp[maxn];
int a[105];
int main() {
int n,m;
cin >> n >> m;
for(int i=1;i<=n;i++)
cin >> a[i];
memset(dp,0,sizeof(dp));
dp[0]=1;//每次j==a[i]时,dp[j]+=1
for(int i=1;i<=n;i++)
for(int j=m;j>=a[i];j--)
dp[j]+=dp[j-a[i]];//是dp(i-1,j)+dp(i-1,j-a[i])的简写形式
cout <<dp[m] << endl;
return 0;
}