揹包问题——P6567 [NOI Online #3 入门组]买表

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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章