Problem:
Problem B: Potatoes

Problem

がっちょ君はN面の畑とM個の芋を所有している。各畑にはそれぞれ1からNまでの番号が付けられている。がっちょ君は畑に芋を植え収穫することで、芋の数を増やしたいと考えている。

がっちょ君は一人暮らしであり、1人ではK面までの畑しか管理することができない。また、各畑の土の状態や面積は様々で、芋の収穫数や植えることのできる芋の数も様々である。芋を畑iに植えた場合、1年後には畑iに植えた芋1つにつきai個の芋を収穫することができる。ただし、畑iには最大でもbi個の芋しか植えることができない。

がっちょ君がK面以内の畑にM個以内の芋を植えた時、1年後に所有することができる芋の数の最大値を求めてほしい。

Input

入力は以下の形式で与えられる。

N M K
a1 a2 ... aN
b1 b2 ... bN

1行目に3個の整数N, M, Kが空白区切りで与えられる。

2行目にN個の整数aiが空白区切りで与えられる。

3行目にN個の整数biが空白区切りで与えられる。

Constraints

1 ≤ N ≤ 15

1 ≤ M ≤ 104

1 ≤ K ≤ min(N,3)

1 ≤ ai ≤ 103

1 ≤ bi ≤ 104

Output

芋の数の最大値を1行で出力せよ。

Sample Input 1

5 100 3
2 3 4 5 6
50 40 20 10 5

Sample Output 1

280

畑1に40個、畑2に40個、畑3に20個植えることで収穫後に280個の芋を所有することができる。

Sample Input 2

5 100 3
2 3 4 5 100
50 40 20 10 1

Sample Output 2

339

畑2に40個、畑3に20個、畑5に1個植えることで300個の芋を収穫することができ、植えなかった芋と合わせて答えは339になる。

Solution in C# (judge verdict: Accepted)

using System.Collections.Generic;
using System.Linq;
using static System.Math;
using System;

public static class combi
{
    public static IEnumerable<IEnumerable<T>> Comb<T>(this IEnumerable<T> items, int r)
    {
        if (r == 0)
        {
            yield return Enumerable.Empty<T>();
        }
        else
        {
            var i = 1;
            foreach (var x in items)
            {
                var xs = items.Skip(i);
                foreach (var c in Comb(xs, r - 1))
                    yield return c.Before(x);
                i++;
            }
        }
    }
    public static IEnumerable<T> Before<T>(this IEnumerable<T> items, T first)
    {
        yield return first;
        foreach (var i in items)
            yield return i;
    }
}

public class Hello
{
    public static void Main()
    {
        string[] line = Console.ReadLine().Trim().Split(' ');
        var n = int.Parse(line[0]);
        var m = int.Parse(line[1]);
        var k = int.Parse(line[2]);
        line = Console.ReadLine().Trim().Split(' ');
        var a = Array.ConvertAll(line, int.Parse);
        line = Console.ReadLine().Trim().Split(' ');
        var b = Array.ConvertAll(line, int.Parse);
        var w = Enumerable.Range(0, n).Comb(k);
        var ans = 0;
        foreach (var x in w)
        {
            var p = x.ToArray();
            if (k == 3) ans = Max(ans, getPk3(p, m, a, b));
            else if (k == 2) ans = Max(ans, getPk2(p, m, a, b));
            else ans = Max(ans, getPk1(p, m, a, b));
        }
        Console.WriteLine(ans);
    }
    static int getwk3(int a0, int a1, int a2, int b0, int b1, int b2, int m)
    {
        if (m <= b0) return a0 * m;
        else if (m <= b0 + b1) return a0 * b0 + a1 * (m - b0);
        else return a0 * b0 + a1 * b1 + a2 * (m - b0 - b1);
    }
    static int getPk3(int[] p, int m, int[] a, int[] b)
    {
        var a0 = a[p[0]]; var a1 = a[p[1]]; var a2 = a[p[2]];
        var b0 = b[p[0]]; var b1 = b[p[1]]; var b2 = b[p[2]];
        if (m >= b0 + b1 + b2) return a0 * b0 + a1 * b1 + a2 * b2 + m - b0 - b1 - b2;
        if (a0 >= a1 && a1 >= a2) return getwk3(a0, a1, a2, b0, b1, b2, m);
        else if (a1 >= a0 && a0 >= a2) return getwk3(a1, a0, a2, b1, b0, b2, m);
        else if (a2 >= a0 && a0 >= a1) return getwk3(a2, a0, a1, b2, b0, b1, m);
        else if (a2 >= a1 && a1 >= a0) return getwk3(a2, a1, a0, b2, b1, b0, m);
        else if (a0 >= a2 && a2 >= a1) return getwk3(a0, a2, a1, b0, b2, b1, m);
        else return getwk3(a1, a2, a0, b1, b2, b0, m);
    }
    static int getwk2(int a0, int a1, int b0, int b1, int m)
    {
        if (m < b0) return a0 * m;
        else return a0 * b0 + a1 * (m - b0);
    }
    static int getPk2(int[] p, int m, int[] a, int[] b)
    {
        var a0 = a[p[0]]; var a1 = a[p[1]]; var b0 = b[p[0]]; var b1 = b[p[1]];
        if (m >= b0 + b1) return a0 * b0 + a1 * b1 + m - b0 - b1;
        if (a0 >= a1) return getwk2(a0, a1, b0, b1, m);
        else return getwk2(a1, a0, b1, b0, m);
    }
    static int getPk1(int[] p, int m, int[] a, int[] b)
    {
        var w = b[p[0]];
        if (w >= m) return m * a[p[0]];
        else return w * a[p[0]] + m - w;
    }
}