/*
多重背包
zjut 1698 Coins
思路:
根据每个coin的x y值大致得出每种coin最多可取几个,然后用二进制处理产生新的coin,将问题转化为01背包
状态转移:dp[j][k]=min(dp[j-xx[i]][k-yy[i]]+cost[i],dp[j][k]);
*/
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int m,s;
int x[101],y[101],dp[301][301],vis[301][301];
int xx[100001],yy[100001],cost[100001];
const int INF=100000;
int main()
{
int cas;
cin>>cas;
while(cas--)
{
cin>>m>>s;
for(int i=0;i<m;i++)
cin>>x[i]>>y[i];
memset(vis,0,sizeof(vis));
memset(cost,0,sizeof(cost));
int num=0;
for(int i=0;i<m;i++)
{
int ci=pow((s*s)/(x[i]*x[i]+y[i]*y[i])*1.0,0.5);
int k=1;
for(;;)
{
if(k>ci)break;
xx[num]=x[i]*k,yy[num]=y[i]*k;
vis[x[i]*k][y[i]*k]=1;
cost[num++]=k;
ci-=k;
k=k<<1;
}
if(ci&&!vis[x[i]*ci][y[i]*ci])
{
xx[num]=x[i]*ci,yy[num]=y[i]*ci;cost[num++]=ci;vis[x[i]*ci][y[i]*ci]=1;
}
}
for(int i=0;i<=s;i++)
for(int j=0;j<=s;j++)
dp[i][j]=INF;
for(int i=0;i<num;i++)
{
dp[xx[i]][yy[i]]=cost[i];
}
for(int i=0;i<num;i++)
{
for(int j=xx[i];j<=s;j++)
for(int k=yy[i];k<=s;k++)
{
if(j*j+k*k<=s*s)
{
dp[j][k]=min(dp[j-xx[i]][k-yy[i]]+cost[i],dp[j][k]);
}
}
}
int ans=INF;
for(int i=0;i<=s;i++)
for(int j=0;j<=s;j++)
if(i*i+j*j==s*s)
{
ans=min(ans,dp[i][j]);
}
if(ans==INF) cout<<"not possible"<<endl;
else cout<<ans<<endl;
}
}
http://acm.zjut.edu.cn/ShowProblem.aspx?ShowID=1698