#include <stdio.h>
#include <string.h>
#include "math.h"
#include <iostream>
#define MAX(a, b) (a) > (b) ? (a) : (b)
#define MIN(a, b) (a) < (b) ? (a) : (b)
char buf[4096], *ex = buf + 4096, *ch = ex;
using namespace std;
inline bool read(){
if (++ch >= ex) { ch = buf; fread(buf, 1, 4096, stdin); }
return true;
}
inline int scan(int n = 0){
while (read() && (*ch < '0' || *ch > '9'));
do { n = n * 10 + *ch - '0'; } while (read() && *ch >= '0' && *ch <= '9');
return n;
}
// 칸의 재료가 3개 이상이고, 최소 단위 이상의 재료를 가지고 있을 때 while문을 돌면서 재료를 사용하고 산출물의 개수를 1개씩 증가시키며, 남은 재료는 현재 칸에 임시로 저장해둔다
void Devide(int i, int M, int stack[][10], int R[], int Q[], int top[])
{
M = stack[i][top[i] - 1];
if ((M>=3) && (M - R[i] >= 0)){
while ((M >= 3) && (M - R[i] >= 0)){
M -= R[i];
Q[i]++;
}
stack[i][top[i] - 1] = M;
}
}
// 누적 산출물이 최소인 재료를 찾는다
void Minimum(int Q[], int N, int* min, int* temp)
{
(*min) = Q[0];
for (int j = 0; j < N; j++){
if (Q[j] <= (*min)){
(*min) = Q[j];
(*temp) = j;
}
}
}
// 각 재료의 칸들을 오름차순으로 정리한다
void Acending(int N, int top[], int stack[][10])
{
for (int i = 0; i < N; i++){
int min, temp, index;
for (int j = 0; j < top[i]-1; j++){
min = stack[i][j];
for (int k = j; k<top[i]-1; k++){
if (min >= stack[i][k]){
min = stack[i][k];
index = k;
}
}
temp = stack[i][j];
stack[i][j] = min;
stack[i][index] = temp;
}
}
}
int main()
{
#if defined(_DEBUG)
freopen("data.txt", "r", stdin);
#endif
int T; // 테스트 케이스
cin >> T;
for (int testcase = 0; testcase < T; testcase++){
int N; // 재료 종류 수 (1<= N <= 10)
int R[10] = { 0 }; // 재료 단위 (1<= R <= 1,000)
int stack[10][10] = { 0 }; // 재료 칸 수 (1<= stack[][] <= 10)
int usedBox = 0; // 사용된 칸의 수
int top[10] = { 0 }; // 남은 칸의 수
int Q[10] = { 0 }; // 몫(산출물)
int M = 0; // temp
cin >> N;
for (int g = 0; g < N; g++){
cin >> R[g] >> top[g];
for (int h = 0; h < top[g]; h++)
cin >> stack[g][h];
}
Acending(N, top, stack);
int temp = 0;
int min = 0;
while (1){
// 산출물 가장 적은 재료가 더 이상 재료칸을 가지고 있지 않거나, 사용된 재료칸이 10개가 된 경우 while문을 탈출한다
Minimum(Q, N, &min, &temp);
if ((top[temp] == 0) || (usedBox == 10))
break;
// 그렇지 않다면 산출물을 계산하고, 남은 재료는 다음 칸으로 이월시킨다
else{
Devide(temp, M, stack, R, Q, top);
if (top[temp] != 1)
{
stack[temp][top[temp] - 2] += stack[temp][top[temp] - 1];
}
stack[temp][top[temp] - 1] = 0;
top[temp]--;
usedBox++;
}
}
// 재료들의 산출물 값 중 최소가 생산품의 최대 개수가 된다
printf("%d\n", min);
}
return 0;
}
ahn
10년 전