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

/*
????????????????????¬??????MinCostFlow????????????????????????????????????
?????????????????°?????????????????????Primal-dual??? ??????????????????
????????????????????????2,3???????????§???????????????????????¨
*/

/*
RadixHeap
??´??°?????¢dijkstra??§???????????¨?????????
priority_queue???????????????
*/

int nlz(int x) {
    if (x == 0) return 32;
    return __builtin_clz(x);
}
struct RadixHeap {
    typedef pair<int, int> P;
    vector<P> v[32];
    int mi, sz;
    RadixHeap() {
        mi = sz = 0;
    }
    void first(int x, int p) {
        sz = 1;
        mi = x;
        v[0].push_back(P(x, p));
    }
    void push(int x, int p) {
        if (!sz) {
            first(x, p);
            return;
        }
        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;
    }
};

const int INF = 1<<28;
template<int V>
struct MinCostFlow {
    typedef int T;
    typedef pair<T, int> P;
    struct Edge {
        int to, rev;
        int cap;
        T cost;
    };
    vector<Edge> g[V];
    T h[V], dist[V];
    int pv[V], pe[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, -cost});
    }
    /**
     * ????°??????¨???????¨??????????
     *
     * bell?????¢?????????????????????????????¨????????´????????????????????°????????§????§£??????????????¨?????¨???
     *
     * Params:
     *   s = ?§????
     *   t = ??????
     *   f = ?????????
     *   bell = ?????????????????????????????¨??????????????????
     */
    T exec(int s, int t, int f, bool bell = false) {
        T res = 0;
        fill_n(h, V, 0);
        while (f > 0) {
            fill_n(dist, V, INF);
            dist[s] = 0;
            if (bell) {
                bell = false;
                bool update;
                do {
                    update = false;
                    for (int v = 0; v < V; v++) {
                        if (dist[v] == INF) continue;
                        for (int i = 0; i < (int)g[v].size(); i++) {
                            Edge &e = g[v][i];
                            if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
                                dist[e.to] = dist[v] + e.cost;
                                pv[e.to] = v;
                                pe[e.to] = i;
                                update = true;
                            }
                        }
                    }
                } while (update);
            } else {
                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 (dist[v] < p.first) continue;
                    for (int i = 0; i < (int)g[v].size(); i++) {
                        Edge &e = g[v][i];
                        if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
                            dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                            pv[e.to] = v;
                            pe[e.to] = i;
                            que.push(P(dist[e.to], e.to));
                        }
                    }
                }
            }
            if (dist[t] == INF) {
                return -1;
            }
            for (int v = 0; v < V; v++) {
                h[v] += dist[v];
            }

            T d = f;
            for (int v = t; v != s; v = pv[v]) {
                d = min(d, g[pv[v]][pe[v]].cap);
            }
            f -= d;
            res += d * h[t];
            for (int v = t; v != s; v = pv[v]) {
                Edge &e = g[pv[v]][pe[v]];
                e.cap -= d;
                g[v][e.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];

MinCostFlow<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