版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/90679428
题目:POJ1742.
题目大意:给定
种物品,物品
价值为
,数量为
,问
之间多少种面值能被凑出来.
.
一道多重背包的模板,当然可以用二进制拆分或者单调队列优化做,但是感觉这样做很麻烦.
考虑这个问题的特殊性,发现它只是要求可行性,我们是否可以从这里入手优化呢?
若当前正在枚举第 种物品, 表示价值 是否能够被拼凑出来,容易发现前面 种物品造成的影响已经没用了,我们只需要考虑当前第 种物品造成的影响即可.
贪心的想,容易发现如果 的价值可以只通过 枚第 种物品凑出来,我们肯定不考虑比 枚更多的硬币,所以考虑记录一下使 最少需要物品 的数量 .每次枚举到第 种物品的时候先把 数组初始化为 ,转移的时候若发现 或 或 时就不管了,否则就让 .
时间复杂度 .
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=100,M=100000;
int n,m,a[N+9],c[N+9];
int dp[M+9],use[M+9],ans;
Abigail into(){
for (int i=1;i<=n;++i)
scanf("%d",&a[i]);
for (int i=1;i<=n;++i)
scanf("%d",&c[i]);
}
Abigail work(){
for (int i=1;i<=m;++i) dp[i]=0;
dp[0]=1;
for (int i=1;i<=n;++i){
for (int j=0;j<=m;++j) use[j]=0;
for (int j=a[i];j<=m;++j)
if (!dp[j]&&dp[j-a[i]]&&use[j-a[i]]<c[i]) dp[j]=1,use[j]=use[j-a[i]]+1;
}
ans=0;
for (int i=1;i<=m;++i) ans+=dp[i];
}
Abigail outo(){
printf("%d\n",ans);
}
int main(){
while (~scanf("%d%d",&n,&m)&&n+m){
into();
work();
outo();
}
return 0;
}