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.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

using static Atcoder_Template_NetCore3.MyBitUtil;
using static Atcoder_Template_NetCore3.MyInputUtil;
using static System.Console;

namespace Atcoder_Template_NetCore3
{
    class Program
    {
        static void Main()
        {
            var (length, maxValue, reqCount) = ReadInput3<int>();
            var array = new int[length].Select(_ => 1).ToArray();
            var reqs = new Req[reqCount];
            for (int i = 0; i < reqCount; i++)
            {
                var input = ReadInput4<int>();
                reqs[i] = new Req(input.Item1, input.Item2, input.Item3, input.Item4);
            }

            var max = 0;
            var ie = GetEnumerator();
            //var str = string.Join("\r\n", ie.Select(x => string.Join(' ', x)));
            //WriteLine(str);
            //return;
            foreach (var a in ie)
            {
                var score = reqs.Select(r => r.GetPoint(a)).Sum();
                if (score > max) max = score;
            }

            WriteLine(max);

            IEnumerable<int[]> GetEnumerator()
            {
                while (true)
                {
                    yield return array;
                    for (int j = 1; j <= array.Length; j++)
                    {
                        if (array[^j] == maxValue)
                        {
                            if (j == array.Length)
                            {
                                yield break;
                            }
                            continue;
                        }
                        else
                        {
                            array[^j]++;
                            var x = array[^j];
                            for (int k = j; k > 0; k--)
                            {
                                array[^k] = x;
                            }
                            break;
                        }
                    }
                }
            }
        }

        struct Req
        {
            private readonly int a;
            private readonly int b;
            private readonly int c;
            private readonly int d;

            public int GetPoint(int[] arr)
            {
                if (arr[b] - arr[a] == c)
                {
                    return d;
                }
                else
                {
                    return 0;
                }
            }

            public Req(int a, int b, int c, int d)
            {
                this.a = a - 1;
                this.b = b - 1;
                this.c = c;
                this.d = d;
            }
        }
    }

    /// <summary>
    /// Bit取得、およびbit全探索を提供します。
    /// </summary>
    internal static class MyBitUtil
    {
        /// <summary>
        /// 指定の桁のビットを取得します。
        /// </summary>
        /// <param name="count">取得する桁。</param>
        /// <returns></returns>
        public static int GetBit(this int num, int count)
        {
            var x = num >> (count - 1);
            const int mask = 1;
            return x & mask;
        }

        /// <summary>
        /// 各ビットの値を <see cref="int"/> 配列として取得します。
        /// 下位の桁が配列の前に来ます。
        /// </summary>
        public static int[] ToBitArray(this int num)
        {
            const int size = sizeof(int) * 8;
            var array = new int[size];
            for (var i = 0; i < size; i++)
            {
                array[i] = num.GetBit(i + 1);
            }
            return array;
        }

        public static int BitToInt32(int[] bitArray)
        {
            var result = 0;
            for (int i = 0; i < bitArray.Length; i++)
            {
                result += bitArray[i] << i;
            }
            return result;
        }

        /// <summary>
        /// 各ビットを真偽値として解釈した結果を <see cref="bool"/> 配列として取得します。
        /// 下位の桁が配列の前に来ます。
        /// </summary>
        public static bool[] ToBoolArray(this int num)
        {
            const int size = sizeof(int) * 8;
            var array = new bool[size];
            for (var i = 0; i < size; i++)
            {
                array[i] = num.GetBit(i + 1) == 1;
            }
            return array;
        }

        /// <summary>
        /// Bit全探索を行います。
        /// </summary>
        /// <param name="count">対象とする要素の個数。30以下である必要があります。</param>
        /// <param name="action">各パターンに対して行う処理</param>
        public static void BitAllSearch(int count, Action<bool[]> action)
        {
            var max = 1 << count;
            for (var i = 0; i < max; i++)
            {
                action.Invoke(i.ToBoolArray());
            }
        }

        /// <summary>
        /// 指定したコレクションに対してBit全探索を行います。
        /// </summary>
        /// <param name="list">対象とする集合。要素数30以下である必要があります。</param>
        /// <param name="action">各パターンに対して行う処理</param>
        public static IEnumerable<IEnumerable<T>> GetAllPatterns<T>(this IReadOnlyList<T> list)
        {
            var max = 1 << list.Count;
            for (var i = 0; i < max; i++)
            {
                var usePattern = i.ToBoolArray();
                IEnumerable<T> query = list.Where((item, j) => usePattern[j]);
                yield return query;
            }
        }
    }

    /// <summary>
    /// 標準入力の高機能な読み取りを提供します。
    /// </summary>
    internal static class MyInputUtil
    {
        private const char separator = ' ';

        /// <summary>
        /// 標準入力から入力を1つ指定の型に変換して読み取ります。
        /// </summary>
        /// <typeparam name="T">変換先として指定する型。</typeparam>
        /// <param name="converter">変換に使用する関数。<c>null</c>の場合は自動決定を試みます。</param>
        /// <returns></returns>
        public static T ReadInput<T>(Func<string, T> converter = null)
        {
            if (converter is null)
            {
                converter = GetConverter<T>();
            }
            return converter.Invoke(Console.ReadLine());
        }

        #region 一定個数の入力の読み取り
        // 用法は ReadInput<T> と共通です。
        [GeneratedCode(null, "2.1")]
        public static ValueTuple<T, T> ReadInput2<T>(Func<string, T> converter = null)
        {
            if (converter is null) { converter = GetConverter<T>(); }
            var input = Console.ReadLine().Split(separator);
            return (converter.Invoke(input[0]), converter.Invoke(input[1]));
        }
        [GeneratedCode(null, "2.1")]
        public static ValueTuple<T, T, T> ReadInput3<T>(Func<string, T> converter = null)
        {
            if (converter is null) { converter = GetConverter<T>(); }
            var input = Console.ReadLine().Split(separator);
            return (converter.Invoke(input[0]), converter.Invoke(input[1]), converter.Invoke(input[2]));
        }
        [GeneratedCode(null, "2.1")]
        public static ValueTuple<T, T, T, T> ReadInput4<T>(Func<string, T> converter = null)
        {
            if (converter is null) { converter = GetConverter<T>(); }
            var input = Console.ReadLine().Split(separator);
            return (converter.Invoke(input[0]), converter.Invoke(input[1]), converter.Invoke(input[2]), converter.Invoke(input[3]));
        }
        [GeneratedCode(null, "2.1")]
        public static ValueTuple<T, T, T, T, T> ReadInput5<T>(Func<string, T> converter = null)
        {
            if (converter is null) { converter = GetConverter<T>(); }
            var input = Console.ReadLine().Split(separator);
            return (converter.Invoke(input[0]), converter.Invoke(input[1]), converter.Invoke(input[2]), converter.Invoke(input[3]), converter.Invoke(input[4]));
        }
        [GeneratedCode(null, "2.1")]
        public static ValueTuple<T, T, T, T, T, T> ReadInput6<T>(Func<string, T> converter = null)
        {
            if (converter is null) { converter = GetConverter<T>(); }
            var input = Console.ReadLine().Split(separator);
            return (converter.Invoke(input[0]), converter.Invoke(input[1]), converter.Invoke(input[2]), converter.Invoke(input[3]), converter.Invoke(input[4]), converter.Invoke(input[5]));
        }
        [GeneratedCode(null, "2.1")]
        public static ValueTuple<T, T, T, T, T, T, T> ReadInput7<T>(Func<string, T> converter = null)
        {
            if (converter is null) { converter = GetConverter<T>(); }
            var input = Console.ReadLine().Split(separator);
            return (converter.Invoke(input[0]), converter.Invoke(input[1]), converter.Invoke(input[2]), converter.Invoke(input[3]), converter.Invoke(input[4]), converter.Invoke(input[5]), converter.Invoke(input[6]));
        }
        #endregion

        /// <summary>
        /// 標準入力から配列を読み取ります。
        /// </summary>
        /// <returns></returns>
        public static T[] ReadArray<T>(Func<string, T> converter = null)
        {
            var str = ReadLine().Split(separator);
            if (converter is null)
            {
                converter = GetConverter<T>();
            }
            return str.Select(s => converter.Invoke(s)).ToArray();
        }

        #region 変換用メソッド
        /// <summary>
        /// 文字列を指定の型に変換します。
        /// </summary>
        /// <typeparam name="T">変換先の型。すべての組み込み型がサポートされます。</typeparam>
        /// <param name="str">変換元の文字列</param>
        /// <exception cref="NotSupportedException">指定の型引数がサポートされない場合にスローされる例外。</exception>
        /// <remarks>大量の値を処理する場合、このメソッドは低速です。<see cref="ConvertTo{T}(string[])"/> の使用を検討してください。</remarks>
        public static T ConvertTo<T>(string str)
        {
            return GetConverter<T>().Invoke(str);
        }

        /// <summary>
        /// 文字列配列を指定の型の配列に変換します。
        /// </summary>
        /// <typeparam name="T">変換先の型。すべての組み込み型がサポートされます。</typeparam>
        /// <param name="str">変換元の文字列配列</param>
        /// <exception cref="NotSupportedException">指定の型引数がサポートされない場合にスローされる例外。</exception>
        public static T[] ConvertTo<T>(string[] str)
        {
            var conveter = GetConverter<T>();
            var array = new T[str.Length];
            for (var i = 0; i < str.Length; i++)
            {
                array[i] = conveter.Invoke(str[i]);
            }
            return array;
        }

        private static Func<string, T> GetConverter<T>() => GetConverterOrDefault<T>() ?? throw new NotSupportedException("この型に対する変換関数の取得はサポートされていません");
        private static bool TryGetConverter<T>(out Func<string, T> func)
        {
            func = GetConverterOrDefault<T>();
            return !(func is null);
        }

        private static Func<string, T> GetConverterOrDefault<T>()
        {
            Type type = typeof(T);
            Func<string, T> conveter;

            // 出現頻度が高そうなものを上
            if (type == typeof(int))
            {
                conveter = str => (T)(object)int.Parse(str);
            }
            else if (type == typeof(long))
            {
                conveter = str => (T)(object)long.Parse(str);
            }
            else if (type == typeof(double))
            {
                conveter = str => (T)(object)double.Parse(str);
            }
            else if (type == typeof(decimal))
            {
                conveter = str => (T)(object)decimal.Parse(str);
            }
            else if (type == typeof(float))
            {
                conveter = str => (T)(object)float.Parse(str);
            }
            else if (type == typeof(char))
            {
                conveter = str => (T)(object)str[0];
            }
            else if (type == typeof(short))
            {
                conveter = str => (T)(object)short.Parse(str);
            }
            else if (type == typeof(byte))
            {
                conveter = str => (T)(object)byte.Parse(str);
            }
            else if (type == typeof(bool))
            {
                conveter = str => (T)(object)bool.Parse(str);
            }
            else if (type == typeof(ulong))
            {
                conveter = str => (T)(object)ulong.Parse(str);
            }
            else if (type == typeof(uint))
            {
                conveter = str => (T)(object)uint.Parse(str);
            }
            else if (type == typeof(ushort))
            {
                conveter = str => (T)(object)ushort.Parse(str);
            }
            else if (type == typeof(sbyte))
            {
                conveter = str => (T)(object)sbyte.Parse(str);
            }
            else if (type == typeof(string))
            {
                conveter = str => (T)(object)str;
            }
            else if (type == typeof(object))
            {
                conveter = str => (T)(object)str;
            }
            else
            {
                conveter = null;
            }

            return conveter;
        }
        #endregion
    }
}