小偷的背包
设有一个背包可以放入的物品重量为S,现有n件物品,重量分别是w1,w2,w3,...,wn。问能否从这n件物品中选择若干件放入背包中,使得放入的重量之和正好为S。如果有满足条件的选择,则此背包有解,否则此背包问题无解。
输入
第一行为物品重量S(整数);
第二行为物品数量n,
第三行为n件物品的重量的序列。
输出
有解就输出”yes!“,没有解就输出”no!“。
样例输入
20
5
1 3 5 7 9
样例输出
yes!
#include<stdio.h>
int a[100];
int f(int s,int n)//遍历所有的组合
{
if(s==0) return 1;
else if(n==0) return 0;
else if(f(s-a[n],n-1)) return 1;//将a【n】放进背包
else return f(s,n-1);//不将a【n】放进背包
}
int main()
{
int s,n;
scanf("%d %d",&s,&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
if(f(s,n))
{
printf("yes!");
}
else
{
printf("no!");
}
}
/*
20
5
5 1 3 7 9
a【1】=5; a【2】=1;a【3】=3;a【4】=7;a【5】=9;
首先是主函数if( f(S,n))
(1)即f(20,5):
if(s==0) return 1;//不成立,进行下一句
if(s!=0&&n==0) return 0;//不成立,进行下一句
if(f(s-a[n],n-1)) return 1;//即f(20- 9,5-1)=f(11,4)
(2)f(11,4):
if(s==0) return 1;//不成立,进行下一句
if(s!=0&&n==0) return 0;//不成立,进行下一句
if(f(s-a[n],n-1)) return 1;//即f(11- 7,4-1)=f(4,3)
(3)f(4,3):
if(s==0) return 1;//不成立,进行下一句
if(s!=0&&n==0) return 0;//不成立,进行下一句
if(f(s-a[n],n-1)) return 1;//即f(4- 3,3-1)=f(1,2)
(4)f(1,2):
if(s==0) return 1;//不成立,进行下一句
if(s!=0&&n==0) return 0;//不成立,进行下一句
if(f(s-a[n],n-1)) return 1;//即f(1-1,2-1)=f(0,1)
(5)f(0,1):
if(s==0) return 1;//成立,返回1,到上一个f函数,即第(4)步
(6) f(1,2)://回到第4步
if(s==0) return 1;//第(4)步已经执行,不成立
if(s!=0&&n==0) return 0;//第(4)步已经执行,不成立
if(f(s-a[n],n-1)) return 1;//即f(1-1,2-1)=f(0,1),第5步执行结果,成立,返回1;回到第3步
(7) f(4,3)://回到第3步
if(s==0) return 1;//第(3)步已经执行,不成立
if(s!=0&&n==0) return 0;//第(3)步已经执行,不成立
if(f(s-a[n],n-1)) return 1;//即f(4- 3,3-1)=f(1,2),第6步执行结果,成立,返回1;回到第2步
(8) f(11,4)://回到第2步
if(s==0) return 1;//第(3)步已经执行,不成立
if(s!=0&&n==0) return 0;//不成立,进行下一句
if(f(s-a[n],n-1)) return 1;//即f(11- 7,4-1)=f(4,3),第7步执行结果,成立,返回1;回到第1步
(9)即f(20,5)://回到第1步
if(s==0) return 1;//不成立,进行下一句
if(s!=0&&n==0) return 0;//不成立,进行下一句
if(f(s-a[n],n-1)) return 1;//即f(20- 9,5-1)=f(11,4) ,,第8步执行结果,成立,返回1;回到主函数 if(f(s,n))为真
程序大致是这样,自己跟踪调试设置断点才是最清楚的
*/