用n件物品(第i件物品费用为ci[i])将背包装满,求背包容量为多少时装不满?此题目为背包问题的拓展,在做第八届蓝桥杯试题包子凑数时,对此问题产生疑惑,本人为新手菜鸟,将背包问题看过后仍然不明白如何求解。看过大神代码后才懂,这里来总结一下,首先应该明白当几组物品的费用不互质时,便会有无限多种背包容量装不满(根据拓展欧几里德),所以应该首先判断所有费用是否最大公约数为1,如果不为1则直接输出INF,为1的情况下,我们将容量推至10010,容量从1到10010进行挨个判断,定义一个数组dp[10010]。这里说下核心思想:背包问题的核心思想都是动态规划,这里也是相同的思想,即每次放某物品前如果背包容量是满的,则放上该物品后的容量一定可以凑满。通过这种思想将数组填满,然后再重头遍历一遍找到个数即可。
#include<iostream>
using namespace std;
int L[100];
int mtGYS(int a,int b){ //求两个数的最大公约数
int max=a>b?a:b;
int result=1;
for(int i=1;i<=max;i++){
if(a%i==0 && b%i==0 && i>result){
result=i;
}
}
return result;
}
int maxGYS(int* a,int n){ //求一组数的最大公约数
int temp[2]={a[0],a[1]};
for(int i=2;i<n;i++){
temp[0]=mtGYS(temp[0],temp[1]);
temp[1]=a[i];
}
return mtGYS(temp[0],temp[1]);
}
int getCount(int* N,int n){ //得到无法凑出的背包容量个数
int V[10010];
V[0]=1;
for(int i=0;i<n;i++){
for(int j=0;j+N[i]<10010;j++){
if(V[j]==1)V[j+N[i]]=1;
}
}
int result=0;
for(int i=0;i<10010;i++){
if(V[i]==0){
result++;
}
}
return result;
}
int main(){
int N;
cin>>N;
for(int i=0;i<N;i++){
cin>>L[i];
}
if(maxGYS(L,N)!=1){
cout<<"INF"<<endl;
}else{
cout<<getCount(L,N)<<endl;
}
return 0;
}