#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <string>
#include <cctype>
#include <vector>
#include <cstdio>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
inline double sqr(double x){
	return x*x;
}
inline int sgn(double x){
	return x<-eps?-1:x>eps;
}
struct Point{
	double x,y,z;
	Point(){}
	Point(double a,double b,double c):
		x(a),y(b),z(c){}
	void input(){
		scanf("%lf%lf%lf",&x,&y,&z);
	}
	void output(){
		printf("%f %f %f\n",x,y,z);
	}
	bool operator == (const Point &p)const{
		return sgn(x - p.x) == 0 && sgn(y - p.y) == 0 && sgn(z - p.z) == 0;
	}
	Point operator * (double k)const{
		return Point(x*k, y*k, z*k);
	}
	Point operator / (double k)const{
		return Point(x/k, y/k, z/k);
	}
	Point operator + (const Point &p)const{
		return Point(x + p.x, y + p.y, z + p.z);
	}
	Point operator - (const Point &p)const{
		return Point(x - p.x, y - p.y, z - p.z);
	}
	double operator / (const Point &p)const{
		return x*p.x + y*p.y + z*p.z;
	}
	Point operator * (const Point &p)const{
		return Point(y*p.z - p.y*z, p.x*z - x*p.z, x*p.y - p.x*y);
	}
	double len2()const{
		return x*x + y*y + z*z;
	}
	double len()const{
		return sqrt(len2());
	}
	double dis2(const Point &p)const{
		return (*this - p).len2();
	}
	double dis(const Point &p)const{
		return (*this - p).len();
	}
	Point scale(double k)const{
		return sgn(len2())?(*this)*(k / len()):(*this);
	}
};
struct Line{
	Point a,b;
	Line(){}
	Line(const Point &x,const Point &y):
		a(x),b(y){}
	Point getVector()const{
		return b - a;
	}
	double len2()const{
		return a.dis2(b);
	}
	double len()const{
		return a.dis(b);
	}
	Point PointToLine(const Point &p)const{
		return a + ((b-a).scale(((b-a)/(p-a))/a.dis(b)));
	}
	double PointDis2Line(const Point &p)const{
		return ((b-a)*(p-a)).len2()/(a.dis2(b));
	}
	bool PointOnLine(const Point &p)const{
		return sgn(((p-a)*(b-a)).len2()) == 0;
	}
	bool PointOnSeg(const Point &p)const{
		return PointOnLine(p) && sgn((p-a)/(p-b))<=0;
	}
	double PointDis2Seg(const Point &p){
		if(PointOnLine(p)){
			if(PointOnSeg(p)) return 0;
			else return min(p.dis2(a),p.dis2(b));
		}
		Point v = PointToLine(p);
		if(PointOnSeg(v)) return PointDis2Line(p);
		else return min(p.dis2(a),p.dis2(b));
	}
	double PointDis2MaxSeg(const Point &p){
		return max(p.dis2(a),p.dis2(b));
	}
};
const int N = 2005,M = 15;
int n,m,k;
Point c[N];
double r[N];
Point d[M];
double g[M];
Point yd;
vector<int> jd[M];
void solve(Point p,vector<int> &v){
	v.clear();
	int cnt = 0;
	Line ln(p,yd);
	for(int i=0;i<n;i++){
		double dis = ln.PointDis2Seg(c[i]);
		if(dis <= r[i] && ln.PointDis2MaxSeg(c[i])>=r[i]){
			v.push_back(i);
			if(++cnt > k){
				//for(int i=0;i<cnt;i++)cout<<v[i]<<" ";
				//cout<<endl;
				return;
			}
		}
	}
	//for(int i=0;i<cnt;i++)cout<<v[i]<<" ";
	//cout<<endl;
}
bool ud[N];
double getg(int op){
	int cnt = 0;
	double ans = 0.0;
	memset(ud,0,n);
	for(int i=0;i<m;i++)if(op>>i&1){
		for(int j=0,sz=jd[i].size();j<sz;j++){
			int v = jd[i][j];
			if(!ud[v]) cnt++;
			if(cnt > k) return 0;
			ud[v] = 1;
		}
		ans += g[i];
	}
	return ans;
}
int main(){
	//freopen("in.txt", "r", stdin);
	while(scanf("%d%d%d",&n,&m,&k),n||m||k){
		for(int i=0;i<n;i++){
			c[i].input();
			scanf("%lf",r+i);
			r[i] *= r[i];
		}
		for(int i=0;i<m;i++){
			d[i].input();
			scanf("%lf",g+i);
		}
		yd.input();
		for(int i=0;i<m;i++){
			g[i] /= d[i].dis2(yd);
			solve(d[i],jd[i]);
		}
		double ans = 0.0;
		for(int i=0,ed=1<<m;i<ed;i++){
			ans = max(ans,getg(i));
		}
		printf("%.15f\n",ans);
	}
	return 0;
}

Measured memory_bytes: 1416