import java.io.BufferedReader;

import java.io.File;

import java.io.FileReader;

import java.io.InputStreamReader;

import java.util.Arrays;

import java.util.Stack;

import java.util.StringTokenizer;


class Solution {


static boolean Debug = false;

static int[] Ticket = new int[4];

static int[] TicketCounter = new int[4];

static int[] Data = new int[12];

static int[] Visited = new int[12];

static int Data_Length = 12;

static int MIN_COST;

static int FIRST_DAY;


public static void main(String args[]) throws Exception {


BufferedReader br;

if (Debug) {

File f = new File("파일경로", "sample_input.txt");

FileReader reader = new FileReader(f);

br = new BufferedReader(reader);

} else {

br = new BufferedReader(new InputStreamReader(System.in)); // 직접입력시 이용

}


StringTokenizer st;


int T_Count = Integer.parseInt(br.readLine());

for (int T = 1; T <= T_Count; T++) {


// 가격정보

st = new StringTokenizer(br.readLine());

for (int i = 0; i < 4; i++) {

Ticket[i] = Integer.parseInt(st.nextToken());

TicketCounter[i] = 0;

}


FIRST_DAY = -1;

// 이용정보

st = new StringTokenizer(br.readLine());

for (int i = 0; i < 12; i++) {

Data[i] = Integer.parseInt(st.nextToken());

Visited[i] = (Data[i] == 0 ? 1 : 0);

if(FIRST_DAY == -1 && Data[i]!=0) {

FIRST_DAY = i;

}

}

MIN_COST = Integer.MAX_VALUE;

findFee();

System.out.println(String.format("#%d %d", T, MIN_COST));

}


}


static int[] rot = new int[] { 1, 30, 120, 360 };


static Stack<Integer> debug = new Stack();

private static void findFee() {


// 순차적 접근을 위하여, 가장 최초 index에서 시작

int next = -1;

for (int i = 0; i < Data_Length; i++) {

if (Visited[i] == 0) {

next = i;

break; 

}

}

if (next == -1) {

log(debug.toString());

writeMinCost();

return;

}


for (int i = 0; i < 4; i++) {

if (!isRight(next, rot[i])) {

continue;

}

checkPay(next, i, true);

debug.add(i);

findFee();

checkPay(next, i, false);

debug.pop();

}


}


private static void checkPay(int index, int rindex, boolean isGo) {


if (rot[rindex] == 1) {

TicketCounter[rindex] += isGo ? Data[index] : -Data[index];

} else {

TicketCounter[rindex] += isGo ? 1 : -1;

}


switch (rot[rindex]) {

case 360:

for (int i = 0; i < Data_Length; i++) {

if (Data[i] == 0) {

continue;

}

Visited[i] = isGo ? 1 : 0;

}

break;

case 120:

for (int i = index; (i < index + 3) && i < Data_Length; i++) {

if (Data[i] == 0) {

continue;

}

Visited[i] = isGo ? 1 : 0;

}

break;

case 30:

case 1:

if (Data[index] == 0) {

return;

}

Visited[index] = isGo ? 1 : 0;

break;

}


}


private static boolean isRight(int index, int day) {

if (Visited[index] == 1 || Data[index] == 0) {

return false;

}


// 비용계산

if (day == 360) {

return index == FIRST_DAY;

} else if (day == 120) {

return  Ticket[2] <= getCost(index, 1, 3) && Ticket[2] <= getCost(index, 30, 3);

} else if (day == 30) {

int month_fee = getCost(index, 30, 1);

int day_fee = getCost(index, 1, 1);

return month_fee <= day_fee;

} else if (day == 1) {

int month_fee = getCost(index, 30, 1);

int day_fee = getCost(index, 1, 1);

return month_fee >= day_fee;

}


return false;

}


private static int getCost(int index, int day, int length) {


if (day == 1) { // 1일로 구매한다면

int day_count = 0;

for (int i = index; i < index + length && i < Data_Length; i++) {

day_count += Data[i];

}

return day_count * Ticket[0];

} else if (day == 30) { // 1달로 구매한다면

int month_count = 0;

for (int i = index; i < index + length && i < Data_Length; i++) {

if (Data[i] > 0) {

month_count += 1;

}

}

return month_count * Ticket[1];

}


return Integer.MAX_VALUE;

}


private static void writeMinCost() {

int sum = 0;


for (int i = 0; i < 4; i++) {

if (TicketCounter[i] != 0) {

sum += (Ticket[i] * TicketCounter[i]);

}

}


if(MIN_COST>sum) {

MIN_COST = sum;

}

}


private static void log(String input) {

if (Debug) {

System.out.println(input);

}

}


}

+ Recent posts