#include<iostream>
using namespace std;
#define N 1000
typedef struct back
{
int value;
int weight;
}back;
back b[N];
int cw,cp,bestp,n,c;
float bound(int t)
{
float a=cp;
int i;
for(i=t;i<=n;i++)
a+=b[i].value;
return a;
}
void Backtrack(int t)
{
if(t>n)
{
if(cp>bestp)
bestp=cp;
return;
}
if(cw+b[t].weight<c)
{
cw+=b[t].weight;
cp+=b[t].value;
Backtrack(t+1);
cw-=b[t].weight;
cp-=b[t].value;
}
if(bound(t+1)>bestp)
Backtrack(t+1);
}
int main()
{
int i;
while(cin>>n>>c)
{
for(i=1;i<=n;i++)
cin>>b[i].value;
for(i=1;i<=n;i++)
cin>>b[i].weight;
Backtrack(1);
cout<<bestp<<endl;
}
return 0;
}
/*
此方法用到了更好的剪枝函数
计算右子树中解的上界时,将剩余物品依其单位重量
价值排序,然后依次装入物品,直至装不下时,再装
入该物品的一部分而装满背包
*/
#include<iostream>
#include<algorithm>
using namespace std;
#define N 1000
typedef struct back
{
int value;
int weight;
}back;
back b[N];
int cw,cp,bestp,n,c;
bool cmp(back b1,back b2)
{
if(b1.value*1.0/b1.weight>b2.value*1.0/b2.weight)
return true;
return false;
}
float bound(int t)
{
float a=cp;
int left=c-cw;
while(left>=b[t].weight&&t<=n)
{
a+=b[t].value;
left-=b[t].weight;
t++;
}
if(t<=n)
{
a+=b[t].value*left*1.0/b[t].weight;
}
return a;
}
void Backtrack(int t)
{
if(t>n)
{
if(cp>bestp)
bestp=cp;
return;
}
if(cw+b[t].weight<c)
{
cw+=b[t].weight;
cp+=b[t].value;
Backtrack(t+1);
cw-=b[t].weight;
cp-=b[t].value;
}
if(bound(t+1)>bestp)
Backtrack(t+1);
}
int main()
{
int i;
while(cin>>n>>c)
{
for(i=1;i<=n;i++)
cin>>b[i].value;
for(i=1;i<=n;i++)
cin>>b[i].weight;
sort(b+1,b+n+1,cmp);
Backtrack(1);
cout<<bestp<<endl;
}
return 0;
}