0-1背包问题
/* 简单背包问题 问题描述 有一个背包,能盛放的物品总重量为s。 设有n件物品,其重量分别为w1,w2,...,wn. 希望从N件物品中选择若干件物品,所选物品的重量之和恰能放入该背包, 即所选物品的重量之和等于s。 若是可以选出满足条件的物品,则为有解,输出yes,然后输出该组物品的编号; 否则为无解,输出no。 注意:n件物品按照输入重量的顺序从1编号到n。 问题解析: 下面的代码用递归来解决问题。 算法根本思想是假设用布尔函数knap(s,n)表示n件物品放入可容质量为s的背包中是否有解 (当knap函数的值为真时,说明问题有解,其值为假时无解)。 我们可以通过输入s和n的值,根据它们的值可分为以下几种情况讨论: (1)当s=0时可知问题有解(不选任何一件或者选了若干件之后剩余容量为0),即函数knap(s,n)的值为true; (2)当s<0时,这时不可能放东西进入背包,所以函数值为false; (3)当s>0且n<1时,即总物品的件数不足1,这时函数值为false。 (4)只有s>0且n≠1时才符合实际情况,这时又分为两种情况: (a)选择的一组物体中不包括Wn,则knap(s,n)的解就是knap(s,n-1)的解. (b)选择的一组物体中包括Wn,则knap(s,n)的解就是knap(s-Wn ,n-1)的解. 这样一组Wn 的值就是问题的最佳解. 这样就将规模为n的问题转化为规模为n-1的问题. 综上所述0- 1 背包问题的递归函数定义为: knap( s, n) =true, s= 0 (不选任何一件或者选了若干件之后剩余容量为0) knap( s, n) =false, s< 0 knap( s, n) =false, s> 0 且n< 1 knap( s, n) =knap( s, n- 1)或knap( s- Wn, n- 1) , s> 0 且n>= 1 采用此法求解0-1背包问题的时间复杂度为O(n)。 上述算法对于所有物品中的某几件恰能装满背包时能准确求出最佳解. 但一般情况是对于某一些物品无论怎么装都不能装满背包, 必须要按背包的最大容量来装.如物品件数为4,其质量分别为: 10, 2, 5, 4。 背包的容量为20, 则这四件物品无论怎么放都不能恰好装满背包, 但应能最大限度装, 即必须装下10, 5, 4 这三件物品, 这样就能得到最大质量19. 这一类问题以后再探讨。 */

1 #include <stdio.h> 2 int w[1005]; 3 int c[1005]; 4 int maxN=1005; 5 //下面这个函数是只返回0和1表示是否有解 6 int f(int s,int n)//这里是要判断把n件物品放到容量s的背包是否有解。n同时是第n件物品的重量数组的下标。 7 { 8 if(s==0) return 1;//正好 9 else if(s<0||(s>0&&n<0)) return 0; //n是物品件数,所以应判断n<0才算是没有物品 10 else if(f(s-w[n],n-1)||f(s,n-1)) return 1;//退出来再选下一个 11 else return 0; 12 } 13 //下面这个函数是在递归过程中不输出结果,递归结束,回到main再输出选中的物品的编号和重量 14 int f2(int s,int n)//这里是要判断把n件物品放到容量s的背包是否有解。n同时是第n件物品的重量数组的下标。 15 { 16 if(s==0) return 1;//正好 17 else if(s<0||(s>0&&n<0)) return 0; //n是物品件数,所以应判断n<0才算是没有物品 18 else if(f2(s-w[n],n-1)==1) 19 { 20 c[n]=1; 21 return 1; 22 } 23 else if(f2(s,n-1)==1) {c[n]=0;return 1;}//退出来再选下一个 24 else return 0; 25 } 26 //下面这个函数可以在递归过程中输出需要选择的物品的编号和重量 27 int f3(int s,int n)//这里是要判断把n件物品放到容量s的背包是否有解。n同时是第n件物品的重量数组的下标。 28 { 29 if(s==0) return 1;//正好 30 else if(s<0||(s>0&&n<0)) return 0; //n是物品件数,所以应判断n<0才算是没有物品 31 else if(f3(s-w[n],n-1)==1) 32 { 33 printf("number:%d weight:%d\n",n+1,w[n]); 34 return 1; 35 } 36 else if(f3(s,n-1)==1) {c[n]=0;return 1;}//退出来再选下一个 37 else return 0; 38 } 39 int main() 40 { 41 freopen("snap_data/snap1.in","r",stdin); 42 freopen("snap_data/snap1.txt","w",stdout); 43 int i,s,n; 44 for(i=0;i<maxN;i++) 45 { 46 w[i]=0; 47 c[i]=0; 48 } 49 scanf("%d%d",&n,&s); 50 for(i=0;i<n;i++) scanf("%d",&w[i]); 51 52 if(f2(s,n-1)==1) 53 { 54 //printf("yes\n"); 55 for(i=0;i<n;i++) 56 { 57 if(c[i]==1) 58 printf("number:%d weight:%d\n",i+1,w[i]); 59 } 60 } 61 else printf("no\n");/**/ 62 63 /*if(f3(s,n-1)==1) 64 { 65 //printf("yes\n"); 66 } 67 else printf("no\n");*/ 68 69 return 0; 70 }
若只是想简单地得到yes和no的结果,可以这样写:

1 #include <stdio.h> 2 #include <stdlib.h> 3 int w[100]={0}; 4 int fun(int x,int T); //判断第x个物品是否可选,当前剩余容量T. 前x个物品(含第x个)刚好能凑够T返回1,否则返回0。 5 int main() 6 { 7 int n,T,i; 8 scanf("%d%d",&n,&T); 9 for(i=1;i<=n;i++) 10 scanf("%d",&w[i]); 11 if(fun(n,T)==1) printf("yes\n"); 12 else printf("no\n"); 13 return 0; 14 } 15 int fun(int x,int T)//判断第x个物品是否可选,当前剩余容量T. 前x个物品(含第x个)刚好能凑够T返回1,否则返回0。 16 { 17 if(w[x]==T) return 1; //假如第x个物品刚好把剩余容量填满,则有解 18 else if(x==1) return 0; //若已经从第n个判断到第1个,而第一个又不能刚好填满剩余容量,则当前的选择不合理 19 else return fun(x-1,T)||fun(x-1,T-w[x]); // 依次尝试选择和不选择第x个物品 20 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App