Problem:
Score : 300 points

Problem Statement

Given are positive integers N, M, Q, and Q quadruples of integers ( a_i , b_i , c_i , d_i ).

Consider a sequence A satisfying the following conditions:

A is a sequence of N positive integers.

1 \leq A_1 \leq A_2 \le \cdots \leq A_N \leq M.

Let us define a score of this sequence as follows:

The score is the sum of d_i over all indices i such that A_{b_i} - A_{a_i} = c_i. (If there is no such i, the score is 0.)

Find the maximum possible score of A.

Constraints

All values in input are integers.

2 ≤ N ≤ 10

1 \leq M \leq 10

1 \leq Q \leq 50

1 \leq a_i < b_i \leq N ( i = 1, 2, ..., Q )

0 \leq c_i \leq M - 1 ( i = 1, 2, ..., Q )

(a_i, b_i, c_i) \neq (a_j, b_j, c_j) (where i \neq j)

1 \leq d_i \leq 10^5 ( i = 1, 2, ..., Q )

Input

Input is given from Standard Input in the following format:

N M Q
a_1 b_1 c_1 d_1
:
a_Q b_Q c_Q d_Q

Output

Print the maximum possible score of A.

Sample Input 1

3 4 3
1 3 3 100
1 2 2 10
2 3 2 10

Sample Output 1

110

When A = \{1, 3, 4\}, its score is 110. Under these conditions, no sequence has a score greater than 110, so the answer is 110.

Sample Input 2

4 6 10
2 4 1 86568
1 4 0 90629
2 3 0 90310
3 4 1 29211
3 4 3 78537
3 4 2 8580
1 2 1 96263
1 4 2 2156
1 2 0 94325
1 4 3 94328

Sample Output 2

357500

Sample Input 3

10 10 1
1 10 9 1

Sample Output 3

1

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Linq;
using System.Collections.Generic;
using System.IO;

namespace AtCoder
{
	class Program
	{
		public static void Main()
		{
#if TextInput
			using(var reader = new StreamReader(Debug.SampleTextPath)) 
			{
				Console.SetIn(reader);
#endif

				var intArray = IO.ReadIntArray();
				N = intArray[0];
				M = intArray[1];
				Q = intArray[2];

				a = new int[Q];
				b = new int[Q];
				c = new int[Q];
				d = new int[Q];
				for(var iIndex = 0 ; iIndex < Q ; ++ iIndex)
				{
					intArray = IO.ReadIntArray();
					a[iIndex] = intArray[0] - 1;
					b[iIndex] = intArray[1] - 1;
					c[iIndex] = intArray[2];
					d[iIndex] = intArray[3];
				}

				A = new int[N];
				_Dfs(0);
				IO.Write(_answer);
#if TextInput
			}
#endif
		}
		private static void _Dfs(int iNestIndex)
		{
			if(iNestIndex == N)
			{
				var sum = 0;
				for(var iIndex = 0 ; iIndex < Q ; ++ iIndex)
				{	
					var answer = A[b[iIndex]] - A[a[iIndex]];
					if(answer == c[iIndex]) { sum += d[iIndex]; }
				}
				_answer = Math.Max(_answer , sum);
			}
			else
			{
				var startIndex = (iNestIndex == 0) ? 0 : A[iNestIndex - 1];
				for(var iIndex = startIndex ; iIndex < M ; ++ iIndex)
				{	
					A[iNestIndex] = iIndex;
					_Dfs(iNestIndex + 1);
				}
			}
		}
		private static int N;
		private static int M;
		private static int Q;
		private static int[] a;
		private static int[] b;
		private static int[] c;
		private static int[] d;
		private static int[] A;
		private static int _answer;
	}

	public static class IO
	{
		public static string   Read()								 { return Console.ReadLine(); }
		public static string[] ReadArray(char iSplitter = ' ')		 { return Read().Split(iSplitter); }
		public static int	   ReadInt()							 { return int.Parse(Read()); }
		public static int[]	   ReadIntArray(char iSplitter = ' ')	 { return ReadArray().Select(iText => int.Parse(iText)).ToArray(); }
		public static long	   ReadLong()							 { return long.Parse(Read()); }
		public static long[]   ReadLongArray(char iSplitter = ' ')	 { return ReadArray().Select(iText => long.Parse(iText)).ToArray(); }
		public static double   ReadDouble()							 { return double.Parse(Read()); }
		public static double[] ReadDoubleArray(char iSplitter = ' ') { return ReadArray().Select(iText => double.Parse(iText)).ToArray(); }
		public static char[]   ReadCharArray()						 { return Read().ToCharArray(); }

		public static void Write(string iValue)	 { Console.WriteLine(iValue); }
		public static void Write(int iValue)	 { Console.WriteLine(iValue); }
		public static void Write(long iValue)	 { Console.WriteLine(iValue); }
		public static void Write(double iValue)  { Console.WriteLine(iValue); }
		public static void Write(decimal iValue) { Console.WriteLine(iValue); }
		public static void Write(bool iValue)	 { Console.WriteLine(iValue ? "Yes" : "No"); }
		public static void Write<Type>(IEnumerable<Type> iValue , string iJoinWord = " ") { Console.WriteLine(string.Join(iJoinWord , iValue)); }
	}

	public static class Util
	{
		public static long Gcd(long i0 , long i1) { return (i0 > i1) ? _Gcd(i0 , i1) : _Gcd(i1 , i0); }
		public static long Lcm(long i0 , long i1) { return (i0 * i1) / Gcd(i0 , i1); }
		public static long ModPow(long iBaseNumber , long iPow , long iModNumber)
		{
			var num = 1L;
			while(iPow != 0)
			{
				if((iPow & 0x1) != 0)
				{
					num = (num * iBaseNumber) % iModNumber;
				}
				iBaseNumber = (iBaseNumber * iBaseNumber) % iModNumber;
				iPow >>= 1;
			}
			return num;
		}
		public static long CombinationNum(int iLeftNumber , int iRightNumber)
		{
			if(iRightNumber == 0) { return 1; }
			if(iLeftNumber == 0)  { return 0; }
			return iLeftNumber * CombinationNum(iLeftNumber - 1 , iRightNumber - 1) / iRightNumber;
		}
		public static long Factorial(long iNumber)
		{
			if(iNumber == 0) { return 1L; }
			return iNumber * Factorial(iNumber - 1);
		}
		private static long _Gcd(long i0 , long i1)	{ return (i1 == 0) ? i0 : _Gcd(i1 , i0 % i1); }
		private static int[] _indexBuf;
	}

	public class UnionFind
	{
		public int[] Parents;
		public int[] RootNums;
		public UnionFind(int iRootNum)
		{
			Parents = Enumerable.Range(0 , iRootNum).ToArray();
			RootNums = new int[iRootNum];
		}
		public void Normalize()
		{
			for(var iIndex = 0 ; iIndex < Parents.Length ; ++ iIndex)
			{
				var rootIndex = _GetRoot(iIndex);
				++ RootNums[rootIndex];
				Parents[iIndex] = rootIndex;
			}
		}
		public void Union(int iNumber0 , int iNumber1)
		{
			var rootNumber0 = _GetRoot(iNumber0);
			var rootNumber1 = _GetRoot(iNumber1);
			if(rootNumber0 < rootNumber1)
			{
				Parents[rootNumber1] = rootNumber0;
			}
			else
			{
				Parents[rootNumber0] = rootNumber1;
			}
		}
		public int _GetRoot(int iNumber)
		{
			return (Parents[iNumber] == iNumber) ? iNumber : _GetRoot(Parents[iNumber]);
		}
	}

	public class CumulativeSum
	{
		public static CumulativeSum Create(IEnumerable<long> iNumbers)
		{
			var numbers = iNumbers.ToArray();
			var cumulativeSum = new CumulativeSum
			{
				Numbers = numbers,
				SumNumbers = new long[numbers.Length + 1]
			};
			var sumNumber = 0L;
			for(var iIndex = 0 ; iIndex < numbers.Length ; ++ iIndex)
			{
				sumNumber += numbers[iIndex];
				cumulativeSum.SumNumbers[iIndex + 1] = sumNumber;
			}
			return cumulativeSum;
		}

		public long[] Numbers { get; private set; }
		public long[] SumNumbers { get; private set; }

		public int GetMaxTotalIndex(int iAreaNum)
		{
			var maxIndex = -1;
			var maxNumber = 0L;
			var num = Numbers.Length - iAreaNum + 1;
			for(var iIndex = 0 ; iIndex < num ; ++ iIndex)
			{
				var checkNumber = SumNumbers[iAreaNum + iIndex] - SumNumbers[iIndex];
				if(maxNumber < checkNumber) 
				{
					maxIndex = iIndex;
					maxNumber = checkNumber;
				}
			}
			return maxIndex;
		}
	}
}