#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 205

struct LOC{

	double x,y;
};

int N,M;
int POW[16];
double dp[15][1<<15][15];
double min_dist[SIZE][SIZE][2][2];
LOC shop[SIZE][2],factory[15];


//scc
int group_index;
bool check[2*SIZE];
int table[2*SIZE];
vector<int> G[2*SIZE];
vector<int> reverse_G[2*SIZE];
stack<int> S;

void dfs(int node_id){
	check[node_id] = true;

	for(int i = 0; i < G[node_id].size(); i++){
		if(!check[G[node_id][i]])dfs(G[node_id][i]);
	}
	S.push(node_id);
}

void reverse_dfs(int node_id){
	check[node_id] = true;

	table[node_id] = group_index;

	for(int i = 0; i < reverse_G[node_id].size(); i++){
		if(!check[reverse_G[node_id][i]])reverse_dfs(reverse_G[node_id][i]);
	}
}

bool is_OK(){

	for(int i = 0; i < 2*N; i++)check[i] = false;

	//まずは帰りがけ順を計算
	for(int i = 0; i < 2*N;i++){
		if(!check[i])dfs(i);
	}

	for(int i = 0; i < 2*N;i++)check[i] = false;

	group_index = -1;
	//ノードを、帰りがけ順の逆順に、各強連結成分(グループ)に分解
	while(!S.empty()){
		if(!check[S.top()]){
			group_index++;

			reverse_dfs(S.top());
		}
		S.pop();
	}

	for(int i = 0; i < N; i++){

		if(table[i] == table[i+N])return false;
	}

	return true;
}

double calc_dist(LOC a,LOC b){

	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}


int main(){

	POW[0] = 1;
	for(int i = 1; i <= 15; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d %d",&N,&M);

	for(int i = 0; i < N; i++){
		for(int k = 0; k < 2; k++){

			scanf("%lf %lf",&shop[i][k].x,&shop[i][k].y);
		}
	}

	for(int i = 0; i < M; i++){

		scanf("%lf %lf",&factory[i].x,&factory[i].y);
	}

	for(int start = 0; start < M; start++){
		for(int state = 0; state < POW[M]; state++){
			for(int last = 0; last < M; last++){

				dp[start][state][last] = BIG_NUM;
			}
		}
		dp[start][POW[start]][start] = 0;
	}

	for(int start = 0; start < M; start++){
		for(int state = 0; state < POW[M]; state++){
			for(int last = 0; last < M; last++){
				if(fabs(dp[start][state][last]-BIG_NUM) < EPS)continue;

				for(int next = 0; next < M; next++){
					if(state & POW[next])continue;

					int next_state = state+POW[next];
					double next_dist = dp[start][state][last]+calc_dist(factory[last],factory[next]);

					dp[start][next_state][next] = min(dp[start][next_state][next],next_dist);
				}
			}
		}
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(k == i)continue;
			for(int a = 0; a < 2; a++){
				for(int b = 0; b < 2; b++){
					min_dist[i][k][a][b] = BIG_NUM;

					for(int start = 0; start < M; start++){
						for(int goal = 0; goal< M; goal++){

							double tmp_dist = calc_dist(shop[i][a],factory[start])+calc_dist(shop[k][b],factory[goal]);
							tmp_dist += dp[start][POW[M]-1][goal];

							min_dist[i][k][a][b] = min(min_dist[i][k][a][b],tmp_dist);
						}
					}
				}
			}
		}
	}

	double left = 0,right = 100000,mid = (left+right)/2;
	double ans = BIG_NUM;

	while(left+EPS < right){

		for(int i = 0; i < 2*SIZE; i++){
			G[i].clear();
			reverse_G[i].clear();
		}

		for(int i = 0; i < N; i++){
			for(int k = 0; k < N; k++){
				if(k == i)continue;
				for(int a = 0; a < 2; a++){
					for(int b = 0; b < 2; b++){

						if(min_dist[i][k][a][b] > mid){ //a→bへはパスを張れない

							int from = i;
							if(a == 1){

								from += N;
							}
							int to = k;
							if(b == 0){ //bが候補0→候補1に辺を張る,bが候補1→候補0に辺を張る

								to += N;
							}
							G[from].push_back(to);
							reverse_G[to].push_back(from);
						}
					}
				}
			}
		}

		if(is_OK()){

			ans = mid;
			right = mid-EPS;
		}else{

			left = mid+EPS;
		}
		mid = (left+right)/2;
	}

	printf("%.10lf\n",ans);

	return 0;
}



Measured memory_bytes: 63640