알고리즘 공부/구현 , 시뮬레이션

[백준] 17825 주사위 윷놀이

kdhoooon 2021. 10. 15. 13:36

 

문제


주사위 윷놀이는 다음과 같은 게임판에서 하는 게임이다.

  • 처음에는 시작 칸에 말 4개가 있다.
  • 말은 게임판에 그려진 화살표의 방향대로만 이동할 수 있다. 말이 파란색 칸에서 이동을 시작하면 파란색 화살표를 타야 하고, 이동하는 도중이거나 파란색이 아닌 칸에서 이동을 시작하면 빨간색 화살표를 타야 한다. 말이 도착 칸으로 이동하면 주사위에 나온 수와 관계 없이 이동을 마친다.
  • 게임은 10개의 턴으로 이루어진다. 매 턴마다 1부터 5까지 한 면에 하나씩 적혀있는 5면체 주사위를 굴리고, 도착 칸에 있지 않은 말을 하나 골라 주사위에 나온 수만큼 이동시킨다.
  • 말이 이동을 마치는 칸에 다른 말이 있으면 그 말은 고를 수 없다. 단, 이동을 마치는 칸이 도착 칸이면 고를 수 있다.
  • 말이 이동을 마칠 때마다 칸에 적혀있는 수가 점수에 추가된다.

주사위에서 나올 수 10개를 미리 알고 있을 때, 얻을 수 있는 점수의 최댓값을 구해보자.

 

 

 

풀이


윷놀이 게임판을 Node 클래스를 선언해서 구현하였다.

static class Node{
	
	int score;
	boolean isEmpty;
	boolean isFinish;
	Node red;
	Node blue;
	
	Node(int score){
		this.score = score;
		this.blue = null;
		this.isEmpty = true;
		this.isFinish = false;
	}
	
	public Node addNext(int score) {
		Node nextNode = new Node(score);
		this.red = nextNode;
		return nextNode;
	}
	
	public static Node getBlueNode(Node start, int target) {
		Node tmp = start;
		while(true) {
			if(tmp == null) {return null;}
			if(tmp.score == target) {return tmp;}
			
			tmp = tmp.red;
		}
	}
}


static void setBoard() {
	
	start = new Node(0);
	
	Node tmp = start;
	for(int i = 2 ; i <= 40 ; i +=2 ) {
		tmp = tmp.addNext(i);
	}
	
	end = tmp.addNext(0);
	end.isFinish = true;
	end.red = end;
	
	Node crossLast = new Node(25);
	tmp = crossLast.addNext(30);
	tmp = tmp.addNext(35);
	tmp.red = Node.getBlueNode(start, 40);
	
	tmp = Node.getBlueNode(start, 10);
	tmp = tmp.blue = new Node(13);
	tmp = tmp.addNext(16);
	tmp = tmp.addNext(19);
	tmp.red = crossLast;
	
	tmp = Node.getBlueNode(start, 20);
	tmp = tmp.blue = new Node(22);
	tmp = tmp.addNext(24);
	tmp.red = crossLast;
	
	tmp = Node.getBlueNode(start, 30);
	tmp = tmp.blue = new Node(28);
	tmp = tmp.addNext(27);
	tmp = tmp.addNext(26);
	tmp.red = crossLast;
	
}

 

red  는 원래 가야하는 화살표

blue 는 지름길로 가는 화살표다.

 

 

이렇게 한 뒤 백트레킹 방식으로 말이 가는 방법을 만들어서 가게 하였다.

그 중 하나라도 겹치는 공간이 생긴다면 그 때는 0을 return 하여 점수를 세지 않는다.

 

static int game() {		
	Arrays.fill(horse, start);
	
	int score = 0;
	
	for(int i = 0 ; i < 10 ; i++) {
		Node now = horse[order[i]];
		now.isEmpty = true;
		
		for(int j =  0 ; j < move[i] ; j++) {
			if(j == 0 && now.blue != null) {
				now = now.blue;
			}
			else {
				now = now.red;
			}
		}
		
		horse[order[i]] = now;
		
		//이미 말이 있다면 불가능한 경우
		if(!now.isEmpty && !now.isFinish) {
			score = 0;
			break;
		}
		else {
			now.isEmpty = false;
			score += now.score;
		}
	}
	
	for(int i = 0 ; i < 4 ; i++) {
		horse[i].isEmpty = true;
	}
	
	return score;
}

static void permutation(int index){
	
	if(index >= 10) {
		answer = Math.max(answer, game());
		return;
	}
	
	for(int i = 0 ; i < 4 ; i++) {
		order[index] = i;
		permutation(index + 1);
	}
}

 

 

 

 

<전체코드>

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {

	
	static int[] move;
	static int[] order;
	static Node[] horse;
	static Node start;
	static Node end;
	static int answer = 0;
	public static void main(String[] args) throws IOException{
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
			
		StringTokenizer st = new StringTokenizer(bufferedReader.readLine());
		move = new int[10];
		order = new int[10];
		horse = new Node[4];
		for(int i = 0 ; i < 10 ; i++) {
			move[i] = Integer.parseInt(st.nextToken());
		}
		
		setBoard();
		permutation(0);
		
		System.out.println(answer);
	}
	
	static int game() {		
		Arrays.fill(horse, start);
		
		int score = 0;
		
		for(int i = 0 ; i < 10 ; i++) {
			Node now = horse[order[i]];
			now.isEmpty = true;
			
			for(int j =  0 ; j < move[i] ; j++) {
				if(j == 0 && now.blue != null) {
					now = now.blue;
				}
				else {
					now = now.red;
				}
			}
			
			horse[order[i]] = now;
			
			//이미 말이 있다면 불가능한 경우
			if(!now.isEmpty && !now.isFinish) {
				score = 0;
				break;
			}
			else {
				now.isEmpty = false;
				score += now.score;
			}
		}
		
		for(int i = 0 ; i < 4 ; i++) {
			horse[i].isEmpty = true;
		}
		
		return score;
	}
	
	static void permutation(int index){
		
		if(index >= 10) {
			answer = Math.max(answer, game());
			return;
		}
		
		for(int i = 0 ; i < 4 ; i++) {
			order[index] = i;
			permutation(index + 1);
		}
	}
	
	static void setBoard() {
		
		start = new Node(0);
		
		Node tmp = start;
		for(int i = 2 ; i <= 40 ; i +=2 ) {
			tmp = tmp.addNext(i);
		}
		
		end = tmp.addNext(0);
		end.isFinish = true;
		end.red = end;
		
		Node crossLast = new Node(25);
		tmp = crossLast.addNext(30);
		tmp = tmp.addNext(35);
		tmp.red = Node.getBlueNode(start, 40);
		
		tmp = Node.getBlueNode(start, 10);
		tmp = tmp.blue = new Node(13);
		tmp = tmp.addNext(16);
		tmp = tmp.addNext(19);
		tmp.red = crossLast;
		
		tmp = Node.getBlueNode(start, 20);
		tmp = tmp.blue = new Node(22);
		tmp = tmp.addNext(24);
		tmp.red = crossLast;
		
		tmp = Node.getBlueNode(start, 30);
		tmp = tmp.blue = new Node(28);
		tmp = tmp.addNext(27);
		tmp = tmp.addNext(26);
		tmp.red = crossLast;
		
	}
	
	static class Node{
		
		int score;
		boolean isEmpty;
		boolean isFinish;
		Node red;
		Node blue;
		
		Node(int score){
			this.score = score;
			this.blue = null;
			this.isEmpty = true;
			this.isFinish = false;
		}
		
		public Node addNext(int score) {
			Node nextNode = new Node(score);
			this.red = nextNode;
			return nextNode;
		}
		
		public static Node getBlueNode(Node start, int target) {
			Node tmp = start;
			while(true) {
				if(tmp == null) {return null;}
				if(tmp.score == target) {return tmp;}
				
				tmp = tmp.red;
			}
		}
	}	
}

'알고리즘 공부 > 구현 , 시뮬레이션' 카테고리의 다른 글

[백준] 20057 마법사 상어와 토네이도  (0) 2021.10.16
[백준] 17822 원판 돌리기  (0) 2021.10.15
[백준] 17143 낚시왕  (0) 2021.10.14
[백준] 1922 쿼드트리  (0) 2021.08.22
[백준] 1074 Z  (0) 2021.08.22