#define _GLIBCXX_DEBUG
#include "bits/stdc++.h"
//#include <intrin.h>  //AtCoder (gcc) 上ではこれがあると動かない。__popcnt用のincludeファイル。
using namespace std;
using Graph = vector<vector<int>>;

typedef long long ll;
typedef long double ld;


#define int long long
#define rep(i, n) for(long long i = 0; i < (n); i++)
#define sqrt(d) pow((long double) (d), 0.50)

const int INF = 2e9;
const ll large_P = 1e9 + 7;



//繰り返し2乗法
//N^aの、Mで割った余りを求める。
ll my_pow(ll N, ll a, ll M) {
	ll tempo;
	if (a == 0) {
		return 1;
	}
	else {
		if (a % 2 == 0) {
			tempo = my_pow(N, a / 2, M);
			return (tempo * tempo) % M;
		}
		else {
			tempo = my_pow(N, a - 1, M);
			return (tempo * N) % M;
		}
	}
}



//N_C_a を M で割った余り
ll my_combination(ll N, ll a, ll M) {
	ll answer = 1;

	rep(i, a) {
		answer *= (N - i);
		answer %= M;
	}

	rep(i, a) {
		answer *= my_pow(i + 1, M - 2, M);
		answer %= M;
	}

	return answer;
}



ll my_gcd(ll& a, ll& b) {
	if (b == 0) return a;
	ll temp = a % b;
	return my_gcd(b, temp);
}



// long long型 n を、base 進法での、i 桁目の数が入った vector にする。
void ll_to_vector(ll base, ll n, vector<ll>& v) {
	ll tempo = n;

	ll n_digit = floor(log10(n) / log10(base)) + 1;
	v.assign(n_digit, 0);

	//ll n_digit = v.size();

	for (ll i = 0; i < n_digit; i++) {
		v.at(i) = tempo / pow(base, n_digit - 1 - i);
		tempo -= v.at(i) * pow(base, n_digit - 1 - i);
	}
}



int char_to_int(char c) {
	switch (c) {
	case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4;
	case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9;
	default: return 0;
	}
}


//エラトステネスの篩で、prime で ないところに false を入れる。
//true で初期化された vector を代入する必要がある。
void prime_judge(vector<bool>& prime_or_not) {

	prime_or_not.at(0) = false;
	prime_or_not.at(1) = false;

	ll n = prime_or_not.size() - 1;
	ll region = sqrt(n) + 1;

	for (ll i = 2; i <= n / 2; i++) {
		prime_or_not.at(2 * i) = false;
	}


	for (ll i2 = 1; i2 < n / 2; i2++) {
		ll i = 2 * i2 + 1;  //ここからは奇数のみ探索
		if (i < region && prime_or_not.at(i)) {
			ll j = i * i;
			while (j < n + 1) {
				prime_or_not.at(j) = false;
				j += 2 * i;
			}
		}
	}
};



map<int, int> divide_to_prime(int target) {
	map<int, int> res;

	//sqrt(target) まで調べる。
	int upper_lim = ceil(sqrt(target));
	vector<bool> prime_or_not(upper_lim + 1, true);

	if (upper_lim < 20) prime_or_not.assign(25, true);
	prime_judge(prime_or_not);

	int tempo = target;
	rep(i, upper_lim + 1) {
		if (prime_or_not.at(i)) {
			while (tempo % i == 0) {
				tempo /= i;
				res[i]++;
			}
		}
	}

	if (tempo != 1) res[tempo]++; //sqrt(target) より大きな素因数は高々1つしかない。



	return res;
}



//後ろから i 番目まで決めている。
int dfs(vector<int>& A, int i, const int M, const vector<int> a, const vector<int> b, const vector<int> c, const vector<int> d, const int sum_d, int& temp_res) {
	int N = A.size();
	int Q = a.size();

	if (temp_res == sum_d) return temp_res;

	if (i == N) {
		int res = 0;
		rep(j, Q) {
			if (A.at(b.at(j)) - A.at(a.at(j)) == c.at(j)) res += d.at(j);
		}
		if (temp_res < res) temp_res = res;
		else res = temp_res;

		return res;
	}

	if(i == 0){
		int res = 0;
		rep(j, M) {
			A.at(N - 1 - i) = j;
			if (res < dfs(A, i + 1, M, a, b, c, d, sum_d, temp_res)) res = dfs(A, i + 1, M, a, b, c, d, sum_d, temp_res);

		}

		if (temp_res < res) temp_res = res;
		else res = temp_res;

		return res;
	}
	else {
		int res = 0;
		for(int j = 0; j <= A.at(N - i); j++) {
			A.at(N - 1 - i) = j;
			if (res < dfs(A, i + 1, M, a, b, c, d, sum_d, temp_res)) res = dfs(A, i + 1, M, a, b, c, d, sum_d, temp_res);
		}

		if (temp_res < res) temp_res = res;
		else res = temp_res;

		return res;
	}
}




signed main() {
	int N, M, Q;
	cin >> N >> M >> Q;

	vector<int> a(Q), b(Q), c(Q), d(Q);
	rep(i, Q) {
		cin >> a.at(i) >> b.at(i) >> c.at(i) >> d.at(i);
		a.at(i)--;
		b.at(i)--;
	}

	int sum_d = 0;
	rep(i, Q) {
		sum_d += d.at(i);
	}

	vector<int> A(N, 0);
	int temp = 0;
	int res = dfs(A, 0, M, a, b, c, d, sum_d, temp);


	cout << res << endl;
}

Measured memory_bytes: 3668