背包问题中求无法装满的种数

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值