背包问题(1)背包的引入

 

 

http://www.cnblogs.com/hansongjiang/p/3810825.html上篇文章我考虑的是可以找零的方式有几种,是运用搜索解决的,但是如果我们要解决的是优化问题,就是说最小要多少硬币呢?

题目的地址是:http://acm.nyist.net/JudgeOnline/problem.php?pid=995其实他是一个背包问题,所以我准备重学一下。

 

 

 

 

最近做硬币找零问题,它实际是个背包问题,很多知识掌握的不扎实。

这里重新总结一下,老规矩,还是靠题目驱动,下面所有题目都给了链接

重复是学习之母

参考了:

http://www.cnblogs.com/jiangjun/archive/2012/05/08/2489590.html

 

1.不算背包的背包

 

题目链接:就为了这个题目,我注册个

账号为zhongguo 密码8421076

http://acm.swust.edu.cn/oj/problem/32/大家可以提交一下试试。

 

设有一个背包可以放入的物品重量为S,现有n件物品,重量分别是w1,w2,w3,…wn。

问能否从这n件物品中选择若干件放入背包中,使得放入的重量之和正好为S。

如果有满足条件的选择,则此背包有解,否则此背包问题无解。

例如  20 能不能有 1 3 5 7 9 组成,我们很容易判断是 1 3 7 9组成 20,所以回答 yes

     10:    12  3   4 不可以组成10,回答No

首先从搜索的角度来看,一个集合有 n个元素,共有 2的n次方可能性,这类问题都可以

通过搜索解决,因为每个元素只有存在集合或者不存在集合当中。

例如{1,4} 共有 4种可能,1 ,4, 1和4 枚举所有可能就可以,搜索的时候当然很多都是不符合答案的,要学会剪枝;

三要素:

递归方程,和对应的条件

初始化的值

然后就很容易转化为代码

递归方程--》转为递归函数

 

递归归函数--》转换为填充数组(动态规划)

 

 

fun(W,S ) W: 当前的还剩下的重量  S:当前还剩下的物品的物品,fun返回true或者false;表示可否组成。

对于第S个物品,选择 变成  fun(W-w[S],S-1)不选,fun(W,S-1)

fun(W,S)=fun(W-w[S],S-1)||fun(W,S-1);

 

#include <iostream>

using namespace std;

const int N=1005;

int w[N];

bool fun(int W,int S)

{

	if(W==0) return true; //剩下钱为0,则返回true;

	if(W<0) return false;

	if(W>0&&S==0) return false; //剩下钱大于0,但是没有物品可选,就是失败

	    return  fun(W-w[S],S-1)||fun(W,S-1);





}



int main()

{

	int W,S;

	

   while(cin>>W>>S)

   {

	  for(int i=1;i<S+1;i++)

	  {

		 

		  cin>>w[i];







	  

	  }



	   if(fun(W,S))

	   {

		   cout<<"YES"<<endl;

	   }

	   else

	   {

		   cout<<"NO"<<endl;

	   }

   

   

   

   

   }

   system("pause");



	return 0;

}

 

 

 

 

 

 

明天再总结一下nyoj 上的背包问题然后总结如何用背包问题一步一步解决硬币找零问题,和把2*n个数,分成2组,没组n个,使他们的和的差最小,编程之美上的,同时也是搜狗的面试。

明天继续

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(问题)