# ZOJ 3631超大背包问题（DFS || 折半搜索）

Watashi's BG

Time Limit: 3 Seconds      Memory Limit: 65536 KB

Watashi is the couch of ZJU-ICPC Team and he is very kind hearted. In ZJU-ICPC summer training camp, students are divided into several groups and each day one of the groups will design some problems to hold a contest. Today students of Group C are required to design the problems, and they spent the whole night to check to test data which made them very tired. Watashi decides to give some money as a reward to group C so that they can buy the lunch for free.

There are N days in the training schedule, and all students have booked their lunch for N days so we know how much money they will spend in each day. Now the leader of group C needs to decide how to use Watashi's money. Since the money is limited, it may not be possible that they can have free lunch every day. So each day the leader can choose to pay for the whole group's lunch by themselves or use Watashi's money. Of course, the leader wants to spend Watashi's money as much as possible, but he is too busy to write a program to calculate the maximum money he can spend from Watashi's reward. Can you help him?

#### Input

The input contains multiple test cases ( no more than 50 test cases ).
In each test case, first there are two integer, N ( 1 <= N <=30 ) , which is the number of training days, M ( 0 <= M <=10000000 ) , which is the reward money from Watashi.
Then there is a line containing N positive integers with the ith integer indicating the money group C need to pay for the lunch of the ith day. All these integers are no more than 10000000 and integers are seperated by a space.

#### Output

For each test case, output one line with an integer which is the maximum money group C can spend from Watashi's reward

#### Sample Input

3 10
8 4 5


#### Sample Output

9

（1）DFS

1.如果结果不能再优则结束所以递归。当答案ans全局变量的值等于背包容量，则结束递归

2.如果容量大于m，结束递归。

3.这里有一个前提，降序排序。如果当前的容量v加上最后一个元素，即最小的元素（a[n-1]）都大于m，那么所有元素加上v都大于m，这时应该结束这个子树的递归（不会搜到更优解 ）。而重新使他的背包容量置为0，搜索其他的子树。

4。第四个剪枝没有想到。就是如果所有物品体积的和<=背包容量，那么就不用搜索啦。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 40
int a[N];
int n,m,ans;
#define inf 0x3f3f3f3f
bool cmp(int x,int y)
{
return x>y;
}
void dfs(int i,int v)
{
if(ans==m)
{
return ;
}
if(v>m||i>n)
{
return ;
}
else
{
// printf("%d %d\n",i,v);
ans=max(ans,v);
}
if(v+a[n-1]>m)
{
dfs(i+1,a[i]);
dfs(i+1,0);
return ;
}
else
{
dfs(i+1,v+a[i]);
dfs(i+1,v);
}
}
int main()
{
#ifdef CDZSC
freopen("i.txt","r",stdin);
#endif
while(~scanf("%d%d",&n,&m))
{
ans=-inf;
int sum=0;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
if(sum<=m)
{
printf("%d\n",sum);
continue;
}
sort(a,a+n,cmp);
dfs(0,0);
printf("%d\n",ans);
}
return 0;
}

2.折半搜索

1.利用二进制的位数变换来表示当前的这个数是否在集合当中：(i>>j)&1，判断第j个元素是否在集合当中。

2.这里我用的是set，不仅自动排序，还能去重。但是使用的时候不能够降序排序（默认升序），这里只能写个结构体重载运算符啦。这一题重点需要解释一下lower_bound函数 若是升序排序那么查找到的是  >=x的位置，而降序排序那么查找到的是  <=x的位置,这一题由题意可知必须要找到 <=x的数字。（话说set的二分查找写起来好轻松啊）

#include<iostream>
#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define N 100
int a[N];
struct point
{
int x;
point (int _x):x(_x){}
point (){}
bool operator<(const point &x1)const
{
return this->x>x1.x;
}

};
set<point>st;
int main()
{
#ifdef CDZSC
freopen("i.txt","r",stdin);
#endif
int n,m;
while(~scanf("%d%d",&n,&m))
{
int ans=-inf;
st.clear();
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int n2=n/2;
for(int i=0;i<(1<<n2);i++)
{
int sw=0;
for(int j=0;j<n2;j++)
{
if((i>>j)&1)
{
sw+=a[j];
}
}
st.insert(point(sw));
}
for(int i=0;i<(1<<(n-n2));i++)
{
int sw=0;
for(int j=0;j<n-n2;j++)
{
if((i>>j)&1)
{
sw+=a[n2+j];
}
}
if(sw<=m)
{
ans=max(st.lower_bound(point(m-sw))->x+sw,ans);
}
}
printf("%d\n",ans);
}
return 0;
}

• 本文已收录于以下专栏：

## hdu 3448 Bag Problem dfs求背包问题

Problem Description 0/1 bag problem should sound familiar to everybody. Every earth man knows it we...
• kongming_acm
• 2011年10月10日 12:10
• 573

## 01背包的DFS解法

01背包是在M件物品取出若干件放在空间为W的背包里，每件物品的体积为W1，W2……Wn，与之相对应的价值为P1,P2……Pn。求出获得最大价值的方案。#include struct t { int...
• oliver233
• 2016年01月27日 21:23
• 340

## 超大背包问题 （折半枚举）

• a2459956664
• 2016年04月19日 15:50
• 1345

## 超大背包问题 折半枚举

• sky_zdk
• 2017年03月05日 10:04
• 192

## 背包问题——“完全背包”详解及实现（包含背包具体物品的求解）

-----Edit by ZhuSenlin HDU         完全背包是在N种物品中选取若干件（同一种物品可多次选取）放在空间为V的背包里，每种物品的体积为C1，C2，…，Cn，与之相对...
• u010304217
• 2014年03月26日 08:53
• 482

## 背包问题加记录路径

• silence401
• 2017年04月03日 18:35
• 595

## 哗啦啦族的01背包问题（折半枚举）

E - 哗啦啦族的01背包问题 Time Limit: 10000/5000MS (Java/Others)    Memory Limit: 128000/64000KB (Java/Others...
• hhhhhhj123
• 2015年09月06日 09:29
• 354

## 超大背包问题 折半枚举法

#include    #include    #include    #include    using namespace std;   typedef long long ll;   ...
• Little_boy_z
• 2017年12月09日 16:52
• 34

## ACDREAM 05E 哗啦啦族的01背包问题（DFS专场）

ACDREAM 05E 哗啦啦族的01背包问题Problem Description背包背包！唐老师非常开心的在给小彭玉讲背包问题，“01背包就是在M件物品取出若干件放在空间为W的背包里，每件物品的体...
• llx523113241
• 2015年06月06日 20:04
• 387

## 背包问题

• Cambridgeacm
• 2012年07月04日 15:37
• 3367

举报原因： 您举报文章：ZOJ 3631超大背包问题（DFS || 折半搜索） 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)