Problem:
Make KND So Fat

Problem

KND君は会津大学に在籍する学生プログラマである。彼の隣人はとても迷惑なことで知られている。隣人は彼が甘党であることを知り、必要以上に甘味を差し入れて彼を太らせようと画策している。そのために、当の隣人であるあなたは友人からとある甘味処を紹介してもらった。

しかし、その甘味処での商品の販売の仕方は少し変わっている。その販売方法とは、甘味セットと呼ばれる甘味の組を日替わりで販売するというものだ。予算内であればその日に販売されている甘味セットの中から自由に甘味を買うことができる。しかし、甘味セットに含まれる甘味は一種類につき１個しか販売されていない。
また、予算は期間の始めに用意した額から支払い、期間途中での追加予算はないものとする。あなたは友人から教えられた甘味の体重に与える影響の度合いと値段をもとに、ある期間中に一定の予算内で彼の体重を最適に増やす甘味の買い方を計算するプログラムを作成することにした。

Input

入力は複数のテストケースからなる。空行区切りで与えられる。ひとつのテストケースは以下の形式で与えられる。入力の終了をEOFで示す。

s d m
k1
w1,1 p1,1 w1,2 p1,2 ... w1,k p1,k
k2
w2,1 p2,1 w2,2 p2,2 ... w2,k p2,k
...
ks
ws,1 ps,1 ws,2 ps,2 ... ws,k ps,k
f1 f2 ... fd

ここで、

s:甘味セットの種類

d:対象となる期間

m:予算

ki:i番目の甘味セットに含まれる甘味の種類数

wi,j:i番目の甘味セットに含まれるj番目の甘味の体重に与える影響

pi,j:i番目の甘味セットに含まれるj番目の甘味の値段

fi:i日目に販売されている甘味セットの番号(0から始まる)

である。

Constraints

入力は以下の条件を満たす。

入力はすべて整数。

1 ≤ s ≤ d ≤ 100

1 ≤ m ≤ 300

1 ≤ ki ≤ 50

0 ≤ wi,j ≤ 50

0 ≤ pi,j ≤ 300

0 ≤ fi < s

Output

各テストケースにつき予算内で体重に与えられる最大の影響とその影響を与えるために必要な最小の金額を空白区切りで1行に出力せよ。

Sample Input

3 3 100
2
5 20 3 10
2
10 50 12 60
2
8 30 22 100
0 1 2

1 1 30
1
13 8
0

Sample Output

23 100
13 8

Solution in C (judge verdict: Accepted)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* constant */

#define MAX_D	(100)
#define MAX_M	(300)
#define MAX_K	(50)

/* typedef */

typedef struct _wp_t {
  int w, p;
} wp_t;

/* global variables */

static int sn, dn, m;
static int kis[MAX_D], fs[MAX_D];
static wp_t swts[MAX_D][MAX_K];
static int ws[MAX_D + 1][MAX_M + 1], dws[MAX_M + 1];

/* main */

int main(int argc, char **argv) {
  int d, dwi, f, i, j, k, max_w, min_p, pk, pu, wku;
  wp_t *swpt;

  while (scanf("%d %d %d", &sn, &dn, &m) == 3) {
    for (i = 0; i < sn; i++) {
      scanf("%d", &(kis[i]));
      for (j = 0; j < kis[i]; j++)
	scanf("%d %d", &(swts[i][j].w), &(swts[i][j].p));
    }

    for (i = 0; i < dn; i++)
      scanf("%d", &(fs[i]));

    bzero(ws, sizeof(ws));

    for (d = 0; d < dn; d++) {
      bzero(dws, sizeof(dws));

      f = fs[d];

      for (i = 0; i < kis[f]; i++) {
	swpt = &(swts[f][i]);

	for (pk = m; pk >= swpt->p; pk--) {
	  dwi = dws[pk - swpt->p] + swpt->w;
	  if (dws[pk] < dwi) dws[pk] = dwi;
	}
      }

      for (pk = 0; pk <= m; pk++) {
	for (pu = 0; pu <= pk; pu++) {
	  wku = ws[d][pk - pu] + dws[pu];
	  if (ws[d + 1][pk] < wku) ws[d + 1][pk] = wku;
	}
      }
    }

    max_w = 0;
    min_p = 0;

    for (pk = 0; pk <= m; pk++) {
      if (max_w < ws[dn][pk]) {
	max_w = ws[dn][pk];
	min_p = pk;
      }
    }

    printf("%d %d\n", max_w, min_p);
  }

  return 0;
}