2014
03-23

# Bag Problem

0/1 bag problem should sound familiar to everybody. Every earth man knows it well. Here is a mutant: given the capacity of a bag, that is to say, the number of goods the bag can carry (has nothing to do with the volume of the goods), and the weight it can carry. Given the weight of all goods, write a program that can output, under the limit in the above statements, the highest weight.

Input will consist of multiple test cases The first line will contain two integers n (n<=40) and m, indicating the number of goods and the weight it can carry. Then follows a number k, indicating the number of goods, k <=40. Then k line follows, indicating the weight of each goods The parameters that haven’t been mentioned specifically fall into the range of 1 to 1000000000.

Input will consist of multiple test cases The first line will contain two integers n (n<=40) and m, indicating the number of goods and the weight it can carry. Then follows a number k, indicating the number of goods, k <=40. Then k line follows, indicating the weight of each goods The parameters that haven’t been mentioned specifically fall into the range of 1 to 1000000000.

5 100
8
8 64 17 23 91 32 17 12
5 10
3
99 99 99

99
0

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int f[55];
int Max;
int n,V,m;
bool hash[55];

void dfs(int x,int cnt,int s){ // 表示 到第x个物品，取了cnt个，总价值s
if(cnt>n||x>m) return;
if(s>Max) Max=s;
int i;
// int num=0;
// long long ss=s;
// for(i=m;i>=1;i--){
//  if(hash[i]==0){
//   ss+=f[i];
//   num++;
//  }
//  if(num+cnt==n) break;
// }
// if(ss<V) {Max=ss;return;}

for(i=x+1;i<=m;i++) {
if(hash[i]==0) {

if(s+f[i]>V) continue;
hash[i]=1;
dfs(x+1,cnt+1,s+f[i]);
hash[i]=0;
}
}
}

int main()
{
while(scanf("%d%d",&n,&V)!=EOF) {

scanf("%d",&m);

for(int i=1;i<=m;i++)
scanf("%d",f+i);

sort(f+1,f+1+m);   //排序

// 38~42行,是剪枝, 不加就TLE,加了就 15MS，有时 0MS
// 14-23行类似
long long ss=0;   //注意要用64位，不然n个大的物品加起来可能就超 int 了
for(int i=m;i>m-n;i--) ss+=f[i];    //求最大的n个物品总价值
if(f[1]>V) ss=0;

if(ss<V) {printf("%I64d/n",ss);continue;} //如果最大的n个物品总和比V小，就不用搜了

Max=0;

memset(hash,0,sizeof(hash));

dfs(0,0,0);     // 表示 到第0个物品，取了0个，总价值0

printf("%d/n",Max);
}
}

1. 约瑟夫也用说这么长……很成熟的一个问题了，分治的方法解起来o(n)就可以了，有兴趣可以看看具体数学的第一章，关于约瑟夫问题推导出了一系列的结论，很漂亮