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.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using static System.Console;

namespace AtCoder
{
	public static class Program
	{
		public static void Main(string[] args)
		{
			var nmq = ReadLine().SplitToIntList();
			var data = ReadAllLines()
				.Select(SplitToIntList)
				.ToList();
			Enumerable
				.Range(1, nmq[1])
				.Select(a => new List<int>().Chain(b => b.Add(a)))
				.Recurse(a =>
				{
					return a.SelectMany(b =>
					{
						return b[^1]
							.Recurse(c => c + 1)
							.TakeWhile(c => c <= nmq[1])
							.Select(c => b.Append(c).ToList());
					});
				})
				.SelectMany(a => a)
				.SkipWhile(a => a.Count < nmq[0])
				.TakeWhile(a => a.Count <= nmq[0])
				.Select(a =>
				{
					return data
						.Where(b => a[b[1] - 1] - a[b[0] - 1] == b[2])
						.Select(b => b[3])
						.Sum();
				})
				.Max()
				.WriteLine();
		}

		#region Utilities

		public interface IBuffer<out T> : IEnumerable<T>, IDisposable
		{ }

		public static IEnumerable<IList<T>> Buffer<T>(
			this IEnumerable<T> source,
			int count)
		{
			return Buffer(source, count, count);
		}

		public static IEnumerable<IList<T>> Buffer<T>(
			this IEnumerable<T> source,
			int count,
			int skip)
		{
			if (source == null)
				throw new ArgumentNullException(nameof(source));
			if (count < 1)
				throw new ArgumentOutOfRangeException(nameof(count));
			if (skip < 1)
				throw new ArgumentOutOfRangeException(nameof(skip));

			var queue = new Queue<List<T>>();
			int step = skip;
			foreach (var item in source)
			{
				if (step == skip)
				{
					step = 0;
					queue.Enqueue(new List<T>(count));
				}
				foreach (var list in queue)
					list.Add(item);
				while (queue.Count > 0 && queue.Peek().Count == count)
					yield return queue.Dequeue();
				step++;
			}
			while (queue.Count > 0) yield return queue.Dequeue();
		}

		public static IEnumerable<IList<T>> Buffer<T>(
			this IEnumerable<T> source,
			Func<T, bool> seperator,
			bool includeSeperator = false)
		{
			if (source == null)
				throw new ArgumentNullException(nameof(source));
			if (seperator == null)
				throw new ArgumentNullException(nameof(seperator));

			var list = new List<T>();
			foreach (var item in source)
			{
				if (seperator(item))
				{
					if (includeSeperator) list.Add(item);
					yield return list;
					list = new List<T>();
				}
				else
				{
					list.Add(item);
				}
			}
			yield return list;
		}

		public static TResult Chain<TSource, TResult>(
			this TSource source,
			Func<TSource, TResult> selector)
		{
			return selector(source);
		}

		public static T Chain<T>(
			this T source,
			Action<T> action)
		{
			action(source);
			return source;
		}

		public static IEnumerable<IEnumerable<T>> Combination<T>(
			this IEnumerable<T> source,
			int count)
		{
			var stack = new Stack<List<T>[]>();
			stack.Push(new[]
			{
				new List<T>(),
				source.ToList()
			});
			while (stack.Count > 0)
			{
				var item = stack.Pop();
				if (item[0].Count() == count)
				{
					yield return item[0];
				}
				else
				{
					var list = item[1];
					list
						.Select((a, i) => new[]
						{
							item[0].Concat(new[]{ a }).ToList(),
							list.Skip(i + 1).ToList(),
						})
						.TakeWhile(a => a[0].Count + a[1].Count >= count)
						.ForEach(a => stack.Push(a));
				}
			}
		}

		public static IEnumerable<T> Concat<T>(this IEnumerable<IEnumerable<T>> source)
		{
			if (source == null)
				throw new ArgumentNullException(nameof(source));

			return source.SelectMany(a => a);
		}

		public static IEnumerable<T> Do<T>(
			this IEnumerable<T> source,
			Action<T> action)
		{
			foreach (var a in source)
			{
				action(a);
				yield return a;
			}
		}

		public static void ForEach<T>(
			this IEnumerable<T> source,
			Action<T> unlessEmpty,
			Action ifEmpty = null)
		{
			if (unlessEmpty == null)
				throw new ArgumentNullException(nameof(unlessEmpty));

			using var e = source.GetEnumerator();
			if (e.MoveNext())
			{
				do unlessEmpty(e.Current);
				while (e.MoveNext());
			}
			else
			{
				ifEmpty?.Invoke();
			}
		}

		public static void ForEach<T>(
			this IEnumerable<T> source,
			Action<T, int> unlessEmpty,
			Action ifEmpty = null)
		{
			if (unlessEmpty == null)
				throw new ArgumentNullException(nameof(unlessEmpty));

			using var e = source.GetEnumerator();
			if (e.MoveNext())
			{
				int i = 0;
				do
				{
					unlessEmpty(e.Current, i);
					i++;
				} while (e.MoveNext());
			}
			else
			{
				ifEmpty?.Invoke();
			}
		}

		public static string JoinWithSpace<T>(this IEnumerable<T> source)
		{
			return string.Join(" ", source);
		}

		public static IEnumerable<IEnumerable<T>> Permutation<T>(
			this IEnumerable<T> source,
			int count)
		{
			var stack = new Stack<IEnumerable<T>[]>();
			stack.Push(new[]
			{
				Enumerable.Empty<T>(),
				source.ToList()
			});
			while (stack.Count > 0)
			{
				var item = stack.Pop();
				if (item[0].Count() == count)
				{
					yield return item[0];
				}
				else
				{
					var list = item[1];
					list
						.Select((a, i) => new[]
						{
							item[0].Concat(new[]{ a }),
							list.Where((b, j) => j != i),
						})
						.ForEach(a => stack.Push(a));
				}
			}
		}

		public static IEnumerable<string> ReadAllLines()
		{
			return Repeat(ReadLine).TakeWhile(a => a != null);
		}

		public static IEnumerable<T> Recurse<T>(
			this T source,
			Func<T, T> selector)
		{
			var p = source;
			while (true)
			{
				yield return p;
				p = selector(p);
			}
		}

		public static IEnumerable<T> Repeat<T>(this T source)
		{
			return Repeat(() => source);
		}

		public static IEnumerable<T> Repeat<T>(Func<T> selector)
		{
			while (true) yield return selector();
		}

		public static IEnumerable<T> Return<T>(params T[] source)
		{
			return source;
		}

		public static IEnumerable<T> Scan<T>(
			this IEnumerable<T> source,
			Func<T, T, T> selector)
		{
			return Scan(source, default, selector);
		}

		public static IEnumerable<T> Scan<T>(
			this IEnumerable<T> source,
			T seed,
			Func<T, T, T> selector)
		{
			var last = seed;
			foreach (var item in source)
			{
				last = selector(last, item);
				yield return last;
			}
		}

		public static IBuffer<T> Share<T>(this IEnumerable<T> source)
		{
			return new SharedBuffer<T>(source);
		}

		public static List<double> SplitToDoubleList(this string source)
		{
			return source.Split().Select(a => double.Parse(a)).ToList();
		}

		public static List<int> SplitToIntList(this string source)
		{
			return source.Split().Select(a => int.Parse(a)).ToList();
		}

		public static T ToVariable<T>(this T source, out T variable)
		{
			variable = source;
			return source;
		}

		public static void WriteAllLines<T>(this IEnumerable<T> source)
		{
			foreach (var item in source) WriteLine(item);
		}

		public static T WriteLine<T>(this T source)
		{
			Console.WriteLine(source);
			return source;
		}

		class SharedBuffer<T> : IBuffer<T>
		{
			private IEnumerator<T> enumerator;

			public SharedBuffer(IEnumerable<T> source)
			{
				enumerator = source.GetEnumerator();
			}

			public void Dispose()
			{
				if (enumerator == null) return;
				enumerator.Dispose();
				enumerator = null;
			}

			public IEnumerator<T> GetEnumerator()
			{
				if (enumerator != null)
				{
					while (enumerator.MoveNext())
					{
						yield return enumerator.Current;
					}
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		#endregion

		#region Location

		struct Location
		{
			public Location(int x, int y)
			{
				X = x;
				Y = y;
			}

			public int X { get; private set; }
			public int Y { get; private set; }

			public static Location operator -(Location left, Location right)
			{
				return new Location(left.X - right.X, left.Y - right.Y);
			}

			public static bool operator !=(Location left, Location right)
			{
				return !(left == right);
			}

			public static Location operator +(Location left, Location right)
			{
				return new Location(left.X + right.X, left.Y + right.Y);
			}

			public static bool operator ==(Location left, Location right)
			{
				return EqualityComparer<Location>.Default.Equals(left, right);
			}

			public override bool Equals(object obj)
			{
				if (!(obj is Location)) return false;
				var other = (Location)obj;
				return other != null &&
					   X == other.X &&
					   Y == other.Y;
			}

			public override int GetHashCode()
			{
				return X << 16 | Y | X >> 16;
			}

			public override string ToString()
			{
				return $"({X},{Y})";
			}
		}

		#endregion

		#region D2

		class D2<T> : IEnumerable<Location>
		{
			public D2(int width, int height, IEnumerable<T> items = null)
			{
				Width = width;
				Height = height;
				var size = Width * Height;
				Items = items?.ToArray() ?? new T[size];
				if (Items.Length != size) throw new Exception();
			}

			public int Height { get; private set; }
			public T[] Items { get; private set; }
			public int Width { get; private set; }

			public T this[int index]
			{
				get { return Items[index]; }
				set { Items[index] = value; }
			}

			public T this[int x, int y]
			{
				get { return Items[y * Width + x]; }
				set { Items[y * Width + x] = value; }
			}

			public T this[Location location]
			{
				get { return this[location.X, location.Y]; }
				set { this[location.X, location.Y] = value; }
			}

			public D2<T> Clone()
			{
				return new D2<T>(Width, Height, Items);
			}

			public bool Contains(Location location)
			{
				return 0 <= location.X
					&& 0 <= location.Y
					&& location.X < Width
					&& location.Y < Height;
			}

			public IEnumerable<IEnumerable<Location>> EnumerateHorizontal()
			{
				return Enumerable
					.Range(0, Width)
					.Select(x => Enumerable
						.Range(0, Height)
						.Select(y => new Location(x, y)));
			}

			public IEnumerable<IEnumerable<Location>> EnumerateVertical()
			{
				return Enumerable
					.Range(0, Height)
					.Select(y => Enumerable
						.Range(0, Width)
						.Select(x => new Location(x, y)));
			}

			public IEnumerator<Location> GetEnumerator()
			{
				foreach (var item in EnumerateVertical().SelectMany(a => a))
				{
					yield return item;
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		#endregion

		#region Matrix

		class Matrix : D2<double>
		{
			public Matrix(int width, int height, IEnumerable<double> items = null) :
				base(width, height, items)
			{
			}

			public static Matrix operator -(Matrix left, Matrix right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				if (right == null) throw new ArgumentNullException(nameof(right));
				if (left.Width != right.Width || left.Height != right.Height)
					throw new ArgumentException(nameof(right));
				return new Matrix(
					left.Width,
					left.Height,
					left.Items.Zip(right.Items, (a, b) => a - b));
			}

			public static Matrix operator -(Matrix left, double right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				return new Matrix(left.Width, left.Height, left.Items.Select(a => a - right));
			}

			public static bool operator !=(Matrix left, Matrix right)
			{
				return !(left == right);
			}

			public static Matrix operator *(Matrix left, Matrix right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				if (right == null) throw new ArgumentNullException(nameof(right));
				if (left.Width != right.Height)
					throw new ArgumentException(nameof(right));
				return new Matrix(
					right.Width,
					left.Height,
					left
						.EnumerateVertical()
						.SelectMany(l => right
							.EnumerateHorizontal()
							.Select(r => l.Zip(r, (a, b) => left[a] * right[b]).Sum())));
			}

			public static Matrix operator *(Matrix left, double right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				return new Matrix(left.Width, left.Height, left.Items.Select(a => a * right));
			}

			public static Matrix operator /(Matrix left, double right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				return new Matrix(left.Width, left.Height, left.Items.Select(a => a / right));
			}

			public static Matrix operator +(Matrix left, Matrix right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				if (right == null) throw new ArgumentNullException(nameof(right));
				if (left.Width != right.Width || left.Height != right.Height)
					throw new ArgumentException(nameof(right));
				return new Matrix(
					left.Width,
					left.Height,
					left.Items.Zip(right.Items, (a, b) => a + b));
			}

			public static Matrix operator +(Matrix left, double right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				return new Matrix(left.Width, left.Height, left.Items.Select(a => a + right));
			}

			public static bool operator ==(Matrix left, Matrix right)
			{
				return EqualityComparer<Matrix>.Default.Equals(left, right);
			}

			public override bool Equals(object obj)
			{
				var other = obj as Matrix;
				return other != null
					&& Width == other.Width
					&& Height == other.Height
					&& Items.Zip(other.Items, (a, b) => a == b).All(a => a);
			}

			public override int GetHashCode()
			{
				int hashCode = 1931280238;
				hashCode = hashCode * -1521134295
					+ Width.GetHashCode()
					+ Height.GetHashCode()
					+ Items.Select(a => a.GetHashCode()).Aggregate((a, b) => a ^ b);
				return hashCode;
			}

			public virtual string ToString(string format)
			{
				return EnumerateVertical()
					.Select(a => string.Join(" ", a.Select(b => this[b].ToString(format))))
					.Chain(a => string.Join("\n", a));
			}

			public override string ToString()
			{
				return ToString("0.00000");
			}
		}

		class PitchMatrix : Matrix
		{
			public PitchMatrix(double radian) : base(3, 3, new[]
			{
				1, 0, 0,
				0, Math.Cos(radian), -Math.Sin(radian),
				0, Math.Sin(radian), Math.Cos(radian),
			})
			{ }

			public PitchMatrix(int degree) : this(Math.PI * degree / 180)
			{ }
		}

		class RollMatrix : Matrix
		{
			public RollMatrix(double radian) : base(3, 3, new[]
			{
				Math.Cos(radian), -Math.Sin(radian), 0,
				Math.Sin(radian), Math.Cos(radian), 0,
				0, 0, 1,
			})
			{ }

			public RollMatrix(int degree) : this(Math.PI * degree / 180)
			{ }
		}

		class RotationMatrix : Matrix
		{
			public RotationMatrix(double radian) : base(2, 2, new[]
			{
				Math.Cos(radian), -Math.Sin(radian),
				Math.Sin(radian), Math.Cos(radian),
			})
			{ }

			public RotationMatrix(int degree) : this(Math.PI * degree / 180)
			{ }
		}

		class YawMatrix : Matrix
		{
			public YawMatrix(double radian) : base(3, 3, new[]
			{
				Math.Cos(radian), 0, -Math.Sin(radian),
				0, 1, 0,
				Math.Sin(radian), 0, Math.Cos(radian),
			})
			{ }

			public YawMatrix(int degree) : this(Math.PI * degree / 180)
			{ }
		}

		#endregion

		#region Prime

		class Prime
		{
			private static readonly bool[] buffer = new bool[4096];
			private static readonly List<int> list = new List<int>();
			private static int mark = 2;

			private Prime()
			{ }

			public static IEnumerable<int> Get()
			{
				return list.Concat(GetNew());
			}

			private static void FillBuffer()
			{
				Array.Clear(buffer, 0, buffer.Length);
				Enumerable
					.Range(0, list.Count)
					.Select(a => list[a])
					.ForEach(a =>
					{
						var o = mark % a;
						var n = o == 0 ? 0 : a - o;
						while (n < buffer.Length)
						{
							buffer[n] = true;
							n += a;
						}
					});
				Enumerable
					.Range(0, buffer.Length)
					.Where(a => !buffer[a])
					.Select(a => mark + a)
					.ForEach(a => (a * 2 - mark)
						.Recurse(b => b + a)
						.TakeWhile(b => b < buffer.Length)
						.ForEach(b => buffer[b] = true));
			}

			private static IEnumerable<int> GetNew()
			{
				while (true)
				{
					FillBuffer();
					int l = list.Count;
					Enumerable
						.Range(0, buffer.Length)
						.Where(a => !buffer[a])
						.ForEach(a => list.Add(mark + a));
					mark += buffer.Length;
					for (int i = l; i < list.Count; i++)
					{
						yield return list[i];
					}
				}
			}
		}

		#endregion
	}
}