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);
}
}
}
'Knowledge > 알고리즘' 카테고리의 다른 글
1949. [모의 SW 역량테스트] 등산로 조성 (0) | 2017.10.07 |
---|---|
2115. [모의 SW 역량테스트] 벌꿀채취 (0) | 2017.10.07 |
[와우패스] 동서남북 복불복 (0) | 2017.10.05 |
2112. [모의 SW 역량테스트] 보호 필름 (0) | 2017.10.05 |
1849. 영준이의 무게측정 [Fail : 오답] (0) | 2017.10.04 |