Time Limit: 10 second
Memory Limit: 2 MB
问题描述
简单的背包问题。设有一个背包,可以放入的重量为s。现有n件物品,重量分别为w1,w2.....wn(1≤i≤n),均为正整数,从n件物品中挑选若干件,使得放入背包的重量之和正好为s。找到一组解即可,如果不存在解,则输出“not found”。
Input
第一行是物品总件数和背包的载重量,第二行为各物品的重量。
Output
各所选物品的序号和重量。(定义输出物品较少的组合)
Sample Input
5 10 1 2 3 4 5
Sample Output
number:1 weight:1
number:4 weight:4
number:5 weight:5
【题解】
这是一个搜索问题。只要枚举每个物品是否在背包中即可。用sum变量来累加,如果sum > v则跳出搜索。因为要找最少物品数量,所以如果当前用掉的物品大于最小值也可以剪枝。当然你得先找到一组解,这个剪枝才有意义。
【代码】
#include <cstdio> int n,v,a[20],sum = 0,min_n = 2100000000,b[20],ans[20]; //min_n在更新一组解之后变成一个剪枝的判断符 void input_data() { scanf("%d %d",&n,&v); for (int i = 1;i <= n;i++) scanf("%d",&a[i]); } void sear_ch(int x,int num) //表示当前枚举到第x个物品,已经装了num个物品 { //可以加上一句 if num >= min_n return... if (sum > v) return; //如果超过了背包的容积则剪枝 if (sum == v) //如果恰好等于容积 则尝试更新答案。 ans是记录答案的数组,b则是动态变化的。 { if (num < min_n) { min_n = num; for (int i = 1;i <= b[0];i++) ans[i] = b[i]; } return; } if ( x > n) return; sum+=a[x]; //表示第x个物品要放进背包中 b[0]++; b[b[0]] = x; sear_ch(x+1,num+1); b[0]--; sum-=a[x]; sear_ch(x+1,num); //表示第x个物品不放进背包中。 } void get_ans() { sear_ch(1,0); } void output_ans() { if (min_n == 2100000000) //记住是“==”,输出无解信息。 { printf("not found"); return; } for (int i = 1;i <= min_n;i++) printf("number:%d weight:%d ",ans[i],a[ans[i]]); } int main() { //freopen("F:\rush.txt","r",stdin); input_data(); get_ans(); output_ans(); return 0; }