#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

enum Type{
	UNKNOWN,
	YES,
	NO,
};

//3次元
struct Point{
	Point(double arg_x,double arg_y,double arg_z){
		x = arg_x;
		y = arg_y;
		z = arg_z;
	}

	Point(){
		x = y = z = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y,z+p.z); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y,z-p.z);}
	Point operator * (double a){ return Point(a*x,a*y,a*z); }
	Point operator / (double a){ return Point(x/a,y/a,z/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y + z*z; }

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS && fabs(z-p.z) < EPS;
	}
	double x,y,z;
};

typedef Point Vector;

struct Line{
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	Point p[2];
};

struct Sphere{
	Point center;
	double r;
};

struct Data{
	Point center;
	double value;
};

int N,M,R;
int POW[16];
Sphere balloon[2000];
Data light[15];
Point E;
double memo[15][2000];
bool check[2000];

//3次元
double norm(Vector a){
	return a.x*a.x+a.y*a.y+a.z*a.z;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y+a.z*b.z;
}

double calc_value(int index){
	return light[index].value/((light[index].center.x-E.x)*(light[index].center.x-E.x)
			+(light[index].center.y-E.y)*(light[index].center.y-E.y)
			+(light[index].center.z-E.z)*(light[index].center.z-E.z));
}

//垂線が引ける場合、交点を求める
Point projection(Line line,Point point){
    double t = dot(point-line.p[0],line.p[0]-line.p[1])/norm(line.p[0]-line.p[1]);
    return line.p[0] + (line.p[0]-line.p[1])*t;
}

bool intersect(int light_index,int balloon_index){

	if(memo[light_index][balloon_index] != UNKNOWN)return memo[light_index][balloon_index] == YES;

	Line line(light[light_index].center,E);

	Point a = line.p[0]-balloon[balloon_index].center, //balloonの中心と光源を結ぶ方向ベクトル
		  b = line.p[1]-balloon[balloon_index].center, //balloonの中心と観測点を結ぶ方向ベクトル
		  c = projection(line,balloon[balloon_index].center)-balloon[balloon_index].center; //balloonの中心から、方向ベクトル()上に下した垂線ベクトル

	if(abs(a) < balloon[balloon_index].r-EPS && abs(b) < balloon[balloon_index].r-EPS && abs(c) < balloon[balloon_index].r-EPS){ //内部に含まれる場合
		memo[light_index][balloon_index] = NO;
		return false;
	}
	if(abs(c) > balloon[balloon_index].r+EPS){ //遠い場合
		memo[light_index][balloon_index] = NO;
		return false;
	}
	if(abs(a) < balloon[balloon_index].r-EPS || abs(b) < balloon[balloon_index].r-EPS){
		memo[light_index][balloon_index] = YES;
		return true;
	}
	if(abs(a-c)+abs(b-c) < abs(a-b)+EPS){
		memo[light_index][balloon_index] = YES;
		return true;
	}
	memo[light_index][balloon_index] = NO;
	return false;
}

void func(){

	for(int i = 0; i < M; i++){
		for(int k = 0; k < N; k++)memo[i][k] = UNKNOWN;
	}

	for(int i = 0; i < N; i++){
		scanf("%lf %lf %lf %lf",&balloon[i].center.x,&balloon[i].center.y,&balloon[i].center.z,&balloon[i].r);
	}
	for(int i = 0; i < M; i++){
		scanf("%lf %lf %lf %lf",&light[i].center.x,&light[i].center.y,&light[i].center.z,&light[i].value);
	}
	scanf("%lf %lf %lf",&E.x,&E.y,&E.z);

	double ans = 0.0,tmp_sum;
	int break_num;

	for(int state = POW[M]; state > 0; state--){ //光を拾う光源の組み合わせを調べる
		break_num = 0;
		tmp_sum = 0.0;
		for(int loop = 0; loop < M; loop++){
			if(state & (1 << loop)){
				tmp_sum += calc_value(loop);
			}
		}
		if(tmp_sum <= ans)continue; //ansより小さいならSKIP

		tmp_sum = 0.0;
		for(int i = 0; i < N; i++)check[i] = false; //割れたらtrue
		for(int loop = 0; loop < M; loop++){
			if(state & (1 << loop)){ //光源loopの光を拾う場合
				tmp_sum += calc_value(loop);
				//交差する（割る）バルーンの数を数える
				for(int i = 0; i < N; i++){
					if(check[i] == false && intersect(loop,i) == true){
						break_num++;
						check[i] = true;
					}
				}

				if(break_num > R)break;
			}
		}
		if(break_num <= R){
			ans = max(ans,tmp_sum);
		}
	}
	printf("%.10lf\n",ans);
}

int main(){

	for(int i = 0; i < 16; i++)POW[i] = pow(2,i);

	while(true){
		scanf("%d %d %d",&N,&M,&R);
		if(N == 0 && M == 0 && R == 0)break;

		func();
	}

	return 0;
}




Measured memory_bytes: 3656