코딩테스트/코드트리_Java
[코드트리 조별과제] 산타와 선물 공장 2
Ski_
2024. 7. 27. 23:00
문제 : 산타와 선물 공장 2
2번 기출을 처음 풀어봐서 좀 더 깔끔하게 풀 수 있는 방법이 있어보이는데, 코드가 더러워서 아쉽다.
LinkedList를 직접 구현하는 방식으로 풀었다.
코드는 아래와 같다
import java.io.*;
import java.util.*;
public class Main {
static class Box {
Box prev, next;
int idx;
}
static class Belt {
Box head, tail;
int cnt = 0;
}
static StringTokenizer st;
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static int q, n, m;
static Box[] boxes;
static Belt[] belts;
public static void init() { // 100
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
belts = new Belt[n + 1];
for (int i = 1; i <= n; i++) belts[i] = new Belt();
boxes = new Box[m + 1];
for (int i = 1; i <= m; i++) boxes[i] = new Box();
ArrayList<Integer>[] beltBoxes = new ArrayList[n + 1];
for (int i = 1; i <= n; i++) beltBoxes[i] = new ArrayList<Integer>();
for (int i = 1; i <= m; i++) {
int location = Integer.parseInt(st.nextToken());
beltBoxes[location].add(i);
}
for (int i = 1; i <= n; i++) {
if (beltBoxes[i].size() == 0) continue;
int size = beltBoxes[i].size();
belts[i].cnt = size;
int boxIdx = beltBoxes[i].get(0);
Box prev = boxes[boxIdx];
prev.idx = boxIdx;
Box next = boxes[boxIdx];
belts[i].head = prev;
for (int s = 1; s < size; s++) {
boxIdx = beltBoxes[i].get(s);
next = boxes[boxIdx];
next.idx = boxIdx;
prev.next = next;
next.prev = prev;
prev = next;
}
belts[i].tail = next;
}
}
public static int moveAll(int m_src, int m_dst) { // 200
int srcCnt = belts[m_src].cnt;
if (srcCnt == 0) return belts[m_dst].cnt; // 만약 출발 벨트가 비어있다면
Belt srcBelt = belts[m_src];
Belt dstBelt = belts[m_dst];
Box prevHead = dstBelt.head;
dstBelt.head = srcBelt.head;
if (prevHead == null) { // 만약 도착 벨트가 비어있는 상태였다면
dstBelt.tail = srcBelt.tail;
} else {
srcBelt.tail.next = prevHead;
prevHead.prev = srcBelt.tail;
}
srcBelt.head = null;
srcBelt.tail = null;
dstBelt.cnt += srcBelt.cnt;
srcBelt.cnt = 0;
return dstBelt.cnt;
}
public static int moveFront(int m_src, int m_dst) { // 300
Belt srcBelt = belts[m_src];
Belt dstBelt = belts[m_dst];
if (srcBelt.cnt == 0 && dstBelt.cnt == 0) return 0; // 두 벨트가 모두 비어있다면
if (srcBelt.cnt == 0) { // src 벨트만 비어있다면
Box dstBox = dstBelt.head;
if (dstBelt.cnt == 1) { //dst 벨트에 박스가 1개만 존재하는 경우
dstBelt.head = null;
dstBelt.tail = null;
} else { // dst 벨트에 박스가 2개이상 존재하는 경우
Box dstNext = dstBox.next;
dstBelt.head = dstNext;
dstNext.prev = null;
}
srcBelt.head = dstBox;
srcBelt.tail = dstBox;
dstBox.next = null;
srcBelt.cnt++;
dstBelt.cnt--;
} else if (dstBelt.cnt == 0) { // dst 벨트만 비어있다면
Box srcBox = srcBelt.head;
if (srcBelt.cnt == 1) { // src 벨트에 박스가 1개만 존재하는 경우
srcBelt.head = null;
srcBelt.tail = null;
} else { // src 벨트에 박스가 2개이상 존재하는 경우
Box srcNext = srcBox.next;
srcBelt.head = srcNext;
srcNext.prev = null;
}
dstBelt.head = srcBox;
dstBelt.tail = srcBox;
srcBox.next = null;
dstBelt.cnt++;
srcBelt.cnt--;
} else {
Box srcBox = srcBelt.head;
Box srcNext = srcBox.next;
Box dstBox = dstBelt.head;
Box dstNext = dstBox.next;
if (srcNext == null && dstNext == null) { // 둘 다 박스가 1개만 존재하는 경우
srcBelt.head = dstBox;
srcBelt.tail = dstBox;
dstBelt.head = srcBox;
dstBelt.tail = srcBox;
} else if (srcNext == null) { // src만 박스가 1개 존재하는 경우
srcBelt.head = dstBox;
srcBelt.tail = dstBox;
dstBox.next = null;
dstBelt.head = srcBox;
srcBox.next = dstNext;
dstNext.prev = srcBox;
} else if (dstNext == null) { // dst만 박스가 1개 존재하는 경우
dstBelt.head = srcBox;
dstBelt.tail = srcBox;
srcBox.next = null;
srcBelt.head = dstBox;
dstBox.next = srcNext;
srcNext.prev = dstBox;
} else {
srcBelt.head = dstBox;
dstBelt.head = srcBox;
dstBox.next = srcNext;
srcNext.prev = dstBox;
srcBox.next = dstNext;
dstNext.prev = srcBox;
}
}
// 진행 이후 m_dst의 선물의 총 수를 출력합니다.
return dstBelt.cnt;
}
public static int moveHalf(int m_src, int m_dst) { // 400
Belt srcBelt = belts[m_src];
Belt dstBelt = belts[m_dst];
if (srcBelt.cnt == 0 || srcBelt.cnt == 1) return dstBelt.cnt;
int floor = srcBelt.cnt / 2;
if (dstBelt.cnt == 0) {
Box head = srcBelt.head;
Box half = srcBelt.head;
for (int i = 1; i < floor; i++) {
half = half.next;
}
Box nextHead = half.next;
srcBelt.head = nextHead;
nextHead.prev = null;
dstBelt.head = head;
dstBelt.tail = half;
half.next = null;
srcBelt.cnt -= floor;
dstBelt.cnt += floor;
} else {
Box srcHead = srcBelt.head;
Box srcHalf = srcBelt.head;
Box dstHead = dstBelt.head;
for (int i = 1; i < floor; i++) {
srcHalf = srcHalf.next;
}
Box srcNextHead = srcHalf.next;
srcBelt.head = srcNextHead;
srcNextHead.prev = null;
dstBelt.head = srcHead;
dstHead.prev = srcHalf;
srcHalf.next = dstHead;
srcBelt.cnt -= floor;
dstBelt.cnt += floor;
}
// 진행 이후 m_dst의 선물의 총 수를 출력합니다.
// 최대 100번까지만 주어집니다.
return dstBelt.cnt;
}
public static int getBoxInfo(int p_num) { // 500
Box box = boxes[p_num];
int prev = -1;
if (box.prev != null) prev = box.prev.idx;
int next = -1;
if (box.next != null) next = box.next.idx;
// prev + 2 * next
return prev + 2 * next;
}
public static int getBeltInfo(int b_num) { // 600
Belt belt = belts[b_num];
int head = -1;
if (belt.head != null) head = belt.head.idx;
int tail = -1;
if (belt.tail != null) tail = belt.tail.idx;
int cnt = belt.cnt;
// head.idx + 2 * tail.idx + 3 * belt.cnt
return head + 2 * tail + 3 * cnt;
}
public static void printBelt() {
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= n; i++) {
sb.append(i + "번 벨트 " + belts[i].cnt + "개 : ");
Box box = belts[i].head;
for (int j = 0; j < belts[i].cnt; j++) {
if (box.prev == null) {
sb.append("null");
} else sb.append(box.prev.idx);
sb.append(" <- ");
sb.append('[');
sb.append(box.idx);
sb.append(']');
sb.append(" -> ");
if (box.next == null) {
sb.append("null");
break;
}
sb.append(box.next.idx).append(" / ");
box = box.next;
}
sb.append('\n');
}
System.out.println(sb);
}
public static void main(String[] args) throws IOException{
q = Integer.parseInt(br.readLine());
while (q-- > 0) {
st = new StringTokenizer(br.readLine());
int cmd = Integer.parseInt(st.nextToken());
switch (cmd) {
case 100:
init();
break;
case 200:
System.out.println(
moveAll(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()))
);
break;
case 300:
System.out.println(
moveFront(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()))
);
break;
case 400:
System.out.println(
moveHalf(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()))
);
break;
case 500:
System.out.println(
getBoxInfo(Integer.parseInt(st.nextToken()))
);
break;
case 600:
System.out.println(
getBeltInfo(Integer.parseInt(st.nextToken()))
);
break;
}
System.out.println("cmd : " + cmd);
printBelt();
}
}
}
반응형