题目传送门
题目大意
给你n件物品和一个容量为w的背包,每件物品只能装入一次
求将背包装到
w
/
2
−
w
w/2-w
w/2−w的一种方案,输出物品数量和装入物品的序号
思路
1、考虑标记是否有存在
w
/
2
−
w
w/2-w
w/2−w的物品,有就可直接输出
2、考虑是否全部的值加起来都小于
w
/
2
w/2
w/2
3、考虑是否全部的值都大于
w
w
w
前三种情况排除后,贪心:讲物品非递减排序,然后从最小的开始依次装入背包,当装入的东西大于
w
/
2
w/2
w/2时即可输出响应的序列
AC Code
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<math.h>
using namespace std;
#define endl '\n'
#define INF 0x3f3f3f3f
#define int long long
#define debug(a) cout<<#a<<"="<<a<<endl;
typedef long long ll;
const double PI=acos(-1.0);
const double e=exp(1.0);
const int M=1e9+7;
const int N=2e5+7;
inline int mymax(int x,int y){return x>y?x:y;}
inline int mymin(int x,int y){return x<y?x:y;}
struct node
{
int da, id;
}a[N];
int n, w;
int sum, flag, idx, l, r;
bool cmp(node a, node b){
return a.da<b.da;
}
void solve(){
cin>>n>>w;
l=(w+1)/2; r=w;
sum=flag=0; idx=-1;
for(int i=1; i<=n; i++){
cin>>a[i].da; a[i].id=i;
if(a[i].da>=l && a[i].da<=r) flag=1, idx=i;
if(a[i].da<l) sum+=a[i].da;
}
if(flag) {cout<<1<<endl<<idx<<endl; return ;}
if(sum<l || sum==0 ) {cout<<"-1"<<endl; return;}
sort(a+1,a+1+n,cmp);
sum=0;
for(int i=1; i<=n; i++){
sum+=a[i].da;
if(sum>=l && sum<=r){
cout<<i<<endl;
for(int j=1; j<=i; j++){
cout<<a[j].id<<" ";
}
cout<<endl;
return ;
}
}
return ;
}
signed main(){
int T;
cin>>T;
while(T--) solve();
return 0;
}