open System
let computeOptCost (budget,N,(opt:int [,]),optFunValue) =
let mutable optCost = 0
for c=budget downto 0 do
if opt.[N,c] = optFunValue then
optCost <- c
else
()
optCost
let computeOptPartySchedule (budget,N,(costs:int[]),(funValues:int[])) =
let OPT = Array2D.zeroCreate (N+1) (budget+1)
for i = 1 to N do
for j = 0 to budget do
let c_i = costs.[i-1] //cost for the ith party
let f_i = funValues.[i-1] // fun value associated with ith party
OPT.[i,j] <-
match j,c_i with
| _ when j<c_i -> OPT.[i-1,j]
| _ -> Math.Max(OPT.[i-1,j],f_i + OPT.[i-1, j-c_i])
// returning (1) summation of all entrance value,
// (2) summation of fun values
((budget,N,OPT,OPT.[N,budget])|>computeOptCost, OPT.[N,budget])
// Example Usage:
//(7,2, [|6;5;|],[|1;1;|])|> computeOptPartySchedule
//(50,10,[|12;15;16;16;10;21;18;12;17;18;|],[|3;8;9;6;2;9;4;4;8;9|]) |> computeOptPartySchedule
//
//(50,10,[|13;19;16;12;10;12;13;15;11;16;|],[|8;10;8;9;2;8;5;5;7;2|]) |> computeOptPartySchedule
//---------------- IO Stuff -------------------
let processHeader () =
let s = Console.ReadLine().Split()
let budget,noOfParties = s.[0]|>int,s.[1]|>int
match budget,noOfParties with
| (0,0) -> None
| _ -> Some(budget,noOfParties)
let parsePartyData n =
let costs = Array.create n 0
let funValues = Array.create n 0
for i = 0 to (n-1) do
System.Console.ReadLine().Split()
|> (fun (s:string []) -> (s.[0]|>int,s.[1]|>int))
|> (fun (x,y) -> costs.[i] <- x; funValues.[i]<-y)
(System.Console.ReadLine()|>ignore) // reading last line that ends this problem instance
costs,funValues
let solve_SPOJ_PARTY () =
let rec solvePartyAux() =
match processHeader() with
| None -> ()
| Some(budget,n) ->
parsePartyData n
|> (fun (costs,funValues) -> (budget, n, costs, funValues))
|> computeOptPartySchedule
|> (fun (optCosts,optFun) -> printfn "%d %d" optCosts optFun)
solvePartyAux()
solvePartyAux()
solve_SPOJ_PARTY ()
b3BlbiBTeXN0ZW0KICAKbGV0IGNvbXB1dGVPcHRDb3N0IChidWRnZXQsTiwob3B0OmludCBbLF0pLG9wdEZ1blZhbHVlKSA9IAogIGxldCBtdXRhYmxlIG9wdENvc3QgPSAwCiAgZm9yICBjPWJ1ZGdldCBkb3dudG8gMCBkbyAKICAgIGlmIG9wdC5bTixjXSA9IG9wdEZ1blZhbHVlIHRoZW4gCiAgICAgIG9wdENvc3QgPC0gYwogICAgZWxzZQogICAgICAoKQogIG9wdENvc3QgCiAKbGV0IGNvbXB1dGVPcHRQYXJ0eVNjaGVkdWxlIChidWRnZXQsTiwoY29zdHM6aW50W10pLChmdW5WYWx1ZXM6aW50W10pKSAgPSAgIAogIGxldCBPUFQgPSBBcnJheTJELnplcm9DcmVhdGUgKE4rMSkgKGJ1ZGdldCsxKQogIAogIGZvciBpID0gMSB0byBOIGRvICAgICAgICAKICAgIGZvciBqID0gMCB0byBidWRnZXQgZG8gCiAgICAgIGxldCBjX2kgPSBjb3N0cy5baS0xXSAvL2Nvc3QgZm9yIHRoZSBpdGggcGFydHkKICAgICAgbGV0IGZfaSA9IGZ1blZhbHVlcy5baS0xXSAvLyBmdW4gdmFsdWUgYXNzb2NpYXRlZCB3aXRoIGl0aCBwYXJ0eQogICAgICAKICAgICAgT1BULltpLGpdIDwtCiAgICAgICAgbWF0Y2ggaixjX2kgd2l0aCAKICAgICAgICB8IF8gd2hlbiBqPGNfaSAtPiBPUFQuW2ktMSxqXQogICAgICAgIHwgXyAgICAgICAgICAgIC0+IE1hdGguTWF4KE9QVC5baS0xLGpdLGZfaSArIE9QVC5baS0xLCBqLWNfaV0pCiAgCiAgLy8gcmV0dXJuaW5nICgxKSBzdW1tYXRpb24gb2YgYWxsIGVudHJhbmNlIHZhbHVlLCAKICAvLyAgICAgICAgICAgKDIpIHN1bW1hdGlvbiBvZiBmdW4gdmFsdWVzCiAgKChidWRnZXQsTixPUFQsT1BULltOLGJ1ZGdldF0pfD5jb21wdXRlT3B0Q29zdCwgT1BULltOLGJ1ZGdldF0pIAoKCi8vIEV4YW1wbGUgVXNhZ2U6Ci8vKDcsMiwgW3w2OzU7fF0sW3wxOzE7fF0pfD4gY29tcHV0ZU9wdFBhcnR5U2NoZWR1bGUKCi8vKDUwLDEwLFt8MTI7MTU7MTY7MTY7MTA7MjE7MTg7MTI7MTc7MTg7fF0sW3wzOzg7OTs2OzI7OTs0OzQ7ODs5fF0pIHw+IGNvbXB1dGVPcHRQYXJ0eVNjaGVkdWxlCi8vCi8vKDUwLDEwLFt8MTM7MTk7MTY7MTI7MTA7MTI7MTM7MTU7MTE7MTY7fF0sW3w4OzEwOzg7OTsyOzg7NTs1Ozc7MnxdKSB8PiBjb21wdXRlT3B0UGFydHlTY2hlZHVsZQoKLy8tLS0tLS0tLS0tLS0tLS0tIElPIFN0dWZmIC0tLS0tLS0tLS0tLS0tLS0tLS0gCmxldCBwcm9jZXNzSGVhZGVyICAoKSA9IAogIGxldCBzID0gQ29uc29sZS5SZWFkTGluZSgpLlNwbGl0KCkKICBsZXQgYnVkZ2V0LG5vT2ZQYXJ0aWVzID0gcy5bMF18PmludCxzLlsxXXw+aW50CgogIG1hdGNoIGJ1ZGdldCxub09mUGFydGllcyB3aXRoIAogIHwgKDAsMCkgLT4gTm9uZSAKICB8IF8gICAgIC0+IFNvbWUoYnVkZ2V0LG5vT2ZQYXJ0aWVzKQoKbGV0IHBhcnNlUGFydHlEYXRhICBuID0gCiAgbGV0IGNvc3RzID0gQXJyYXkuY3JlYXRlIG4gMAogIGxldCBmdW5WYWx1ZXMgPSAgQXJyYXkuY3JlYXRlIG4gMAoKICBmb3IgaSA9IDAgdG8gKG4tMSkgZG8KICAgIFN5c3RlbS5Db25zb2xlLlJlYWRMaW5lKCkuU3BsaXQoKSAKICAgIHw+IChmdW4gKHM6c3RyaW5nIFtdKSAtPiAocy5bMF18PmludCxzLlsxXXw+aW50KSkKICAgIHw+IChmdW4gKHgseSkgLT4gY29zdHMuW2ldIDwtIHg7IGZ1blZhbHVlcy5baV08LXkpCiAgCiAgKFN5c3RlbS5Db25zb2xlLlJlYWRMaW5lKCl8Pmlnbm9yZSkgLy8gcmVhZGluZyBsYXN0IGxpbmUgdGhhdCBlbmRzIHRoaXMgcHJvYmxlbSBpbnN0YW5jZSAKICBjb3N0cyxmdW5WYWx1ZXMKCgpsZXQgc29sdmVfU1BPSl9QQVJUWSAoKSA9IAogIGxldCByZWMgc29sdmVQYXJ0eUF1eCgpID0gCiAgICBtYXRjaCBwcm9jZXNzSGVhZGVyKCkgd2l0aCAKICAgIHwgTm9uZSAtPiAoKSAKICAgIHwgU29tZShidWRnZXQsbikgLT4gCiAgICAgICAgCiAgICAgICAgcGFyc2VQYXJ0eURhdGEgbgogICAgICAgIHw+IChmdW4gKGNvc3RzLGZ1blZhbHVlcykgLT4gKGJ1ZGdldCwgbiwgY29zdHMsIGZ1blZhbHVlcykpCiAgICAgICAgfD4gY29tcHV0ZU9wdFBhcnR5U2NoZWR1bGUgCiAgICAgICAgfD4gKGZ1biAob3B0Q29zdHMsb3B0RnVuKSAgLT4gcHJpbnRmbiAiJWQgJWQiIG9wdENvc3RzIG9wdEZ1bikKICAgICAgICBzb2x2ZVBhcnR5QXV4KCkKCiAgc29sdmVQYXJ0eUF1eCgpCgpzb2x2ZV9TUE9KX1BBUlRZICgpCg==