#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <cassert>
#include <cstdio>
#include <iostream>
#include <unordered_map>

using namespace std;
typedef long long ll;


int nlz(int x) {
    if (x == 0) return 32;
    return __builtin_clz(x);
}
struct RadixHeap {
    typedef pair<int, int> P;
    vector<P> v[32];
    bool f;
    int mi, sz;
    RadixHeap() {
        mi = sz = 0;
        f = false;
    }
    void first(int x, int p) {
        sz = 1;
        mi = x;
        v[0].push_back(P(x, p));
    }
    void push(int x, int p) {
        if (!f) {
            f = true;
            first(x, p);
            return;
        }
        assert(mi <= x);
        sz++;
        v[32-nlz(x^mi)].push_back(P(x, p));
    }
    void push(P p) {
        push(p.first, p.second);
    }
    void renew() {
        assert(!v[0].size());
        int i = 1;
        while (!v[i].size()) i++;
        mi = v[i][0].first;
        for (P &d: v[i]) {
            mi = min(mi, d.first);
        }
        for (P &p: v[i]) {
            v[32-nlz(mi^p.first)].push_back(p);
        }
        v[i].clear();
    }
    P top() {
        if (!v[0].size()) {
            renew();
        }
        assert(v[0].size());
        return v[0].back();
    }
    P pop() {
        sz--;
        if (!v[0].size()) {
            renew();
        }
        P r = v[0].back();
        v[0].pop_back();
        return r;
    }
    int size() {
        return sz;
    }
    bool empty() {
        return sz == 0;
    }
    void clear() {
        mi = sz = 0;
        for (int i = 0; i < 32; i++) {
            v[i].clear();
        }
    }
};

const int INF = 1<<27;
template<int V>
struct MinCostFlowOptimize {
    typedef int T;
    typedef pair<T, int> P;
//    using T = int;
//    using P = pair<T, int>;
    struct Edge {
        int to, rev;
        int cap;
        T cost;
    };
    vector<Edge> g[V];
    void init() {
        for (int i = 0; i < V; i++) {
            g[i].clear();
        }
    }
    void add(int from, int to, int cap, T cost) {
        g[from].push_back(Edge{to, (int)g[to].size(), cap, cost});
        g[to].push_back(Edge{from, (int)g[from].size()-1, 0, (T)(-cost)});
    }

    T h[V], dist[V];
    bool used[V];
    Edge *prev[V];
    T exec(int s, int t, int &f) {
        T res = 0;
        fill_n(h, V, 0);
        while (f > 0) {
            fill_n(dist, V, INF);
            fill_n(used, V, false);
            dist[s] = 0;
            RadixHeap que;
//            priority_queue<P, vector<P>, greater<P>> que;
            que.push(P(0, s));
            while (!que.empty()) {
                P p = que.top(); que.pop();
                int v = p.second;
                if (v == t) break;
                if (used[v]) continue;
                used[v] = true;
                int hv = h[v], distv = dist[v];                
                for (Edge &e: g[v]) {
                    if (!e.cap) continue;
                    T ee = e.cost-hv+h[e.to];
                    if (dist[e.to] > distv+ee) {
                        dist[e.to] = distv+ee;
                        prev[e.to] = &e;
                        que.push(P(dist[e.to], e.to));
                    }
                }
            }
            if (dist[t] == INF) {
                return res;
            }
            for (int v = 0; v < V; v++) {
                if (dist[v] >= dist[t]) continue;
                h[v] += dist[t]-dist[v];
            }
            T d = f;
            for (int v = t; v != s; v = g[v][prev[v]->rev].to) {
                d = min(d, prev[v]->cap);
            }
            f -= d;
            res += d * (h[s]-h[t]);
            for (int v = t; v != s; v = g[v][prev[v]->rev].to) {
                prev[v]->cap -= d;
                g[v][prev[v]->rev].cap += d;
            }
        }
        return res;
    }
};

const int MN = 110;
const int MM = 6;
int n, m, b, k;
int ax[MN], ay[MN];
int bx[MM], by[MM], c[MM], f[MM];

MinCostFlowOptimize<130> mf;

int calc(int md) {
//    printf("startcalc:%d\n", md);
    mf.init();
    /**
     * 0..MN p
     * MN..MN+MM k
     * 120:s 121:t
     */
    int sv = 120, tv = 121;
    for (int i = 0; i < n; i++) {
        mf.add(sv, i, 1, 0);
    }
    for (int i = 0; i < m; i++) {
        if (!(k & (1<<i))) continue;
        mf.add(MN+i, tv, c[i], 0);
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (!(k & (1<<j))) continue;
            mf.add(i, MN+j, 1, max(0, abs(ax[i]-bx[j])+abs(ay[i]-by[j])-md));
        }
    }
    int u = n;
    int res = mf.exec(sv, tv, u);
    return __builtin_popcount(k)*b*md+res;
}

int solve() {
//    printf("solve n:%d\n", n);
    /**
     * 0..MN human
     * MN..MN+MM pos
     * s:120 t:121 S:122 T:123
     */

    int res = 2*1e9;
//    for (k = 0; k < (1<<m); k++) {
    for (k = 1; k < (1<<m); k++) {
        int fr = 0;
        int cc = 0;
        for (int i = 0; i < m; i++) {
            if (!(k & (1<<i))) continue;
            fr += f[i];
            cc += c[i];
        }
        if (cc < n) continue;
        int l = 0, r = 10000;        
        while (r - l > 2) {
            int mdl = (l+l+r)/3, mdr = (l+r+r)/3;
            int dl = calc(mdl), dr = calc(mdr);
//            printf("l:%d dl:%d r:%d dr:%d\n", mdl, dl, mdr, dr);
            if (dl > dr) {
                l = mdl;
            } else {
                r = mdr;
            }
        }
        res = min(res, fr+min(calc(l), calc(r-1)));
    }
    return res;
}

int main() {
    while (true) {
        cin >> n >> m >> b;
        if (!n && !m && !b) break;
        for (int i = 0; i < n; i++) {
            cin >> ax[i] >> ay[i];
        }
        for (int i = 0; i < m; i++) {
            cin >> bx[i] >> by[i] >> c[i] >> f[i];
        }
        cout << solve() << endl;
    }
    return 0;
}

Measured memory_bytes: 1264