#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],dist_BalloonObject[2000],distLightBalloon[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;
}

double calc_dist(Point a,Point b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}

bool intersect(int light_index,int balloon_index){

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

	//balloonの中心と観測点の距離
	double dist_1 = dist_BalloonObject[balloon_index];
	double dist_2 = distLightBalloon[light_index][balloon_index];

	if(dist_1 <= balloon[balloon_index].r && dist_2 <= balloon[balloon_index].r){
		memo[light_index][balloon_index] = NO;  //観測点と光源がballoonの内部にあるなら妨害なし
		return false;
	}

	//方向ベクトル
	double Vx = light[light_index].center.x-E.x;
	double Vy = light[light_index].center.y-E.y;
	double Vz = light[light_index].center.z-E.z;

	//Oを原点,点Aを観測点としたとき、点balloon_indexから下した垂線との交点が、(E_x+t*Vx,E_y+t*Vy,E_z+t*Vz)と表されるようなt
	double t = (Vx*(balloon[balloon_index].center.x-E.x)+Vy*(balloon[balloon_index].center.y-E.y)+Vz*(balloon[balloon_index].center.z-E.z))/(Vx*Vx+Vy*Vy+Vz*Vz);

	if(t < 0 || t > 1){ //垂線が、観測点と光源を結ぶ線分上にない場合→最近地点は、観測点か光源のどちらか
		if(dist_1 > balloon[balloon_index].r && dist_2 > balloon[balloon_index].r){
			memo[light_index][balloon_index] = NO;
			return false;
		}else{
			memo[light_index][balloon_index] = YES;
			return true;
		}
	}

	double cross_x = E.x+t*Vx;
	double cross_y = E.y+t*Vy;
	double cross_z = E.z+t*Vz;

	double dist = sqrt((balloon[balloon_index].center.x-cross_x)*(balloon[balloon_index].center.x-cross_x)
			+(balloon[balloon_index].center.y-cross_y)*(balloon[balloon_index].center.y-cross_y)
			+(balloon[balloon_index].center.z-cross_z)*(balloon[balloon_index].center.z-cross_z)
		);

	if(dist <= balloon[balloon_index].r){
		memo[light_index][balloon_index] = YES;
		return true;
	}else{
		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);

	//balloonの中心と観測地点との距離を計算
	for(int i = 0; i < N; i++){
		dist_BalloonObject[i] = calc_dist(balloon[i].center,E);
	}
	//光源とballoonの中心との距離を計算
	for(int i = 0; i < M; i++){
		for(int k = 0; k < N; k++){
			distLightBalloon[i][k] = calc_dist(light[i].center,balloon[k].center);
		}
	}

	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;
}


