The Robbery

题目描述

某市中心有一家银行,这家银行有一个大金库。金库内有N个非常大的盒子,编号从1到N。在编号为k的盒子内有k个非常大的钻石,每个都是重量和价值

一强盗想偷走全部钻石,但不幸的是,他能够携带总重量不超过M。

你的任务是帮助这名强盗选择总重量小于等于M的最大价值总和的钻石。

输入格式

第一行包含单个整数T—测试用例的数量。

每个测试用例第一行行包含两个整数N和M,用一个空格隔开。第二行行包含由单个空格分隔的N个整数。第三行包含由单个空格分隔的N个整数

输出格式

对于每个测试用例,输出一行,包含一个整数,表示最大能够携带的钻石总价值。

样例

样例输入

2 
2 4 
3 2 
5 3 
3 100 
4 7 1 
5 9 2

样例输出

6 
29

c++AC代码

#include<bits/stdc++.h>
using namespace std;
struct node{
	long long w,c,k;
}a[100005];
long long n,m,sum[100005],ans=-1e9,t;
bool cmp(node x,node y){return x.c*y.w>y.c*x.w;}
//x为当前遍历编号,sum1为价格,sum2为重量 
inline void dfs(long long x,long long sum1,long long sum2){
	if(sum1+sum[x]<=ans)return;
	if(sum1+(m-sum2)*a[x].c*1.0/a[x].w<=ans)return;
	if(sum2==m){
		ans=max(sum1,ans);
		return;
	}
	if(x==n+1){
		if(sum2<=m)ans=max(sum1,ans);
		return;
	}
	for(int i=a[x].k;i>=0;i--){
		if(sum2+a[x].w*i<=m)dfs(x+1,sum1+a[x].c*i,sum2+a[x].w*i);	
	}
} 
int main(){
	scanf("%lld",&t);
	for(int i=1;i<=t;i++){
		ans=-1e9;
		scanf("%d %d",&n,&m);
		for(int j=1;j<=n;j++)scanf("%lld",&a[j].w);
		for(int j=1;j<=n;j++)scanf("%lld",&a[j].c);
		for(int j=1;j<=n;j++)a[j].k=j;
		sort(a+1,a+1+n,cmp);
		for(int j=n;j>=1;j--)sum[j]=sum[j+1]+a[j].c*a[j].k;
		dfs(1,0,0);
		printf("%lld\n",ans);
	}
	return 0;
}
 
posted @ 2021-03-06 12:02  黄逸飞重庆八中  阅读(111)  评论(0编辑  收藏  举报