题目描述
雫露露的生日快要到了,她的 N 个朋友为她准备了礼物,其中第 i 位朋友准备了 ai 份礼物,第 j(1≤j≤ai) 份礼物的空间大小为bi,j。
为了能够更好地接收朋友们的礼物,雫露露提前准备了一个容量为 W 的背包。但是,为了给朋友们留下好印象,她只会从每位朋友那里收取恰好一份礼物。雫露露打算充分利用背包的空间,她想知道有多少种收取礼物的方式,使背包恰好装满。
其中,定义两种收取礼物的方式不同,当且仅当存在一位朋友,两种方式收取了该位朋友不同的礼物。
输出描述:
输出一行一个正整数,表示收取礼物的方案数,使背包恰好装满。
输入:
2 10 2 3 4 3 7 6 7
输出
3
说明:
当选择第 111 位朋友的第 111 份礼物和第 222 位朋友的第 111 份礼物时,礼物的总空间为 b1,1+b2,1=3+7=10恰好装满背包。 当选择第 111 位朋友的第 111 份礼物和第 222 位朋友的第 333 份礼物时,礼物的总空间为 b1,1+b2,3=3+7=10,恰好装满背包。 当选择第 111 位朋友的第 222 份礼物和第 222 位朋友的第 222 份礼物时,礼物的总空间为 b1,2+b2,2=4+6=10恰好装满背包。 除此之外不存在其他的方式恰好装满背包,所以方案数是 3。
我的思路:
这道题是第一次写动态规划类的题 我的思路是先找到结束条件 上一层的层数里背包的总量加上最后一层背包数量正好等于要寻找的 dp[i][w]+=d[i-1][当前背包里所剩余的容量] 这就是当前所需要找的次数 首先找到初始量 dp[当前层数][背包总容量] 其次找到规律: 每一层背包剩余的数量等于总量减去之前所用的所用量
代码:
#include "bits/stdc++.h"
using namespace std;
const int maxn=10e6+10;
const int N=3030;
int dp[3000][3000];
vector<int>a[N];
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int n,w;cin>>n>>w;
for(int i=1;i<=n;i++)
{
int t,x;cin>>t;
for(int j=0;j<t;j++)
{
cin>>x;
a[i].push_back(x);
}
}
dp[0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<a[i].size();j++)
{
for(int k=w;k>=a[i][j];k--)
{
dp[i][k]+=dp[i-1][k-a[i][j]];
}
}
}
cout<<dp[n][w];
return 0;
}