背包问题(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个,使他们的和的差最小,编程之美上的,同时也是搜狗的面试。

明天继续

 

 

 

 

 

 

 

 

 

posted @ 2014-06-27 23:38  hansongjiang8  阅读(267)  评论(0编辑  收藏  举报