https://www.luogu.com.cn/problem/P6567
思路:
给了钱币数
钱币分为面额和张数
还有几块表
感觉就是有n个物品,每个物品的大小和数量已知,求能不能正好放进这个揹包
区别:
动态方程:
完全揹包的方程是将其转换为01揹包后,求在有限的容量内,以特定的物品能产生的最大值
即
for(int i=1;i<=n;i++)
{
for(int j=m;j>=a[i];j--)
{
if(dp[j-a[i]]+c[i]>dp[j]){
dp[j]=dp[j-a[i]]+c[i];
}
}
}
这道题我们想要通过几次运算后看它能不能回到“原点”
即
dp[0]=1;
for(int i=1;i<=s;i++){//s为物品数量
//进来一个物品
for(int j=pur;j>=a[i];j--){
if(dp[j-a[i]]==1){//如果它前面这步能回到原点
dp[j]=1;//那么它也可以
}
}
}
if(dp[pur]==dp[0]){
cout<<"Yes";
break;
}
答案
int n,m;
cin>>n>>m;
int a[n+1],b[n+1];
//输入+转换
int s=0;//转换后物品数量,为定义数组用
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
s+=b[i];
}
int p[s+1];
int q=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=b[i];j++){
p[q++]=a[i];
}
}
for(int k=1;k<=m;k++){
int pur;
cin>>pur;
//pur=3
int dp[pur+1];
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=1;i<=s;i++){
for(int j=pur;j>=p[i];j--){
if(dp[j-p[i]]==1){
dp[j]=1;
}
}
if(dp[pur]==1){
cout<<"Yes";
break;
}
}
if(dp[pur]==0){
cout<<"No";
}
cout<<endl;
}