'메모' 카테고리의 다른 글

[스크랩] 데이비드 헨리 소우로  (0) 2018.03.26
[스크랩] 로크와 홈스 사회계약설  (0) 2018.03.25
디자인 0130  (0) 2018.01.30

import java.io.BufferedReader;

import java.io.File;

import java.io.FileReader;

import java.io.InputStreamReader;

import java.util.ArrayList;

import java.util.HashSet;

import java.util.Stack;

import java.util.StringTokenizer;


class Point {

int y, x;


public Point(int y, int x) {

this.y = y;

this.x = x;

}

}


class Process {

int y, x;


public Process(int y, int x) {

this.y = y;

this.x = x;

}


HashSet<Point> moveSet = new HashSet();


public boolean on(int rIndex) {

// 해당 방향으로 전선을 잇는다.


int nextY = y;

int nextX = x;

int endIndex = Solution.MapSize - 1;


while (true) {

nextY += Solution.rotY[rIndex];

nextX += Solution.rotX[rIndex];


if (isRight(nextY, nextX)) {

// 경로기록

moveSet.add(new Point(nextY, nextX));

//경계지점에 도달

if (nextX == 0 || nextY == 0 || nextX == endIndex || nextY == endIndex) {

// 전선연결

for (Point item : moveSet) {

Solution.Visited[item.y][item.x] = 1;

}


return true;

}

} else {

// 경로 삭제

moveSet.clear();

return false;

}

}

}


public boolean isRight(int y, int x) {

if (x < 0 || y < 0 || x >= Solution.MapSize || y >= Solution.MapSize) {

// 배열범위

return false;

} else if (Solution.Visited[y][x] != 0) {

// 해당구획

return false;

}

return true;

}


public void off() {

// 전선을 제거한다.

for (Point item : moveSet) {

Solution.Visited[item.y][item.x] = 0;

}


moveSet.clear();

}


}


class Solution {


static boolean Debug = true;

private static int T;

static int MapSize;


static int[][] Visited; // 시간정보

private static ArrayList<Process> pList;

private static int processLen;

private static int[] checkMin;


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


BufferedReader br;

if (Debug) {

File f = new File("C:\\Users\\wvimi\\Downloads", "sample_input (14).txt");

FileReader reader = new FileReader(f);

br = new BufferedReader(reader);

} else {

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

}


StringTokenizer st;


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

for (T = 1; T <= TestSize; T++) {


// 맵의 크기

MapSize = Integer.parseInt(br.readLine());


// 프로세스 리스트

pList = new ArrayList<>();

Visited = new int[MapSize][];


// Map 읽기

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

// Map[i] = new int[MapSize];

Visited[i] = new int[MapSize];

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

for (int j = 0; j < MapSize; j++) {


int item = Integer.parseInt(st.nextToken());

// 맵, Visited 초기화

Visited[i][j] = item == 1 ? 2 : item; // 0:빈공간, 1:방문, 2:프로세스


// 프로세스 등록

if (item == 1) {

boolean inner = i != 0 && j != 0 && i != MapSize - 1 && j != MapSize - 1;

if (inner) {

// 관리 프로세스에 등록

pList.add(new Process(i, j));

}

}


}

}


offProcLen = Integer.MAX_VALUE;

processLen = pList.size();

checkMin = new int[13];


// 최대 값을 저장할 배열

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

checkMin[i] = Integer.MAX_VALUE;

}


// 탐색

findPath(0, 0);


// 결과 출력

for (int i = 11; i >= 0; i--) {

// 성공한 길이를 탐색

if (checkMin[i] != Integer.MAX_VALUE) {

System.out.println(String.format("#%d %d", T, checkMin[i]));

break;

}

// 그 어떤 전선도 없는 경우

if (i == 0) {

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

}

}


}


}


static int offProcLen; // 도달한 0의 개수 (브레이크 조건으로 활용)

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


private static void findPath(int index, int bitmask) {


// 끝지점에 도달

if (index == processLen) {


// 0을 몇 번 썼는지 체크

int count_one = countOne(bitmask);

int offLen = processLen - count_one;

if (offProcLen > offLen) {

offProcLen = offLen;

}


// 전선의 길이

int length = 0;

for (Process process : pList) {

length += process.moveSet.size();

}


// 프로세스 개수 별로 최대 개수를 달리한다.

if (checkMin[count_one] > length) {

checkMin[count_one] = length;

}


return;

}


Process item = pList.get(index);


// 프로세스에 전선을 잇는 경우

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

// 연결이 가능한 경우에만 탐색

int nextBitmask = bitmask + (1 << index);


// 최대 끌 수 있는 프로세스를 고려 (1개까지 꺼서 성공했으면, 2개는 허용 못함)

if (index + 1 - countOne(nextBitmask) <= offProcLen)

if (item.on(i)) {

// debStack.add(i + 1);

findPath(index + 1, nextBitmask);

item.off();

// debStack.pop();

}

}


// 프로세스에 전선을 잇지 않는 경우

// debStack.add(0);

findPath(index + 1, bitmask);

// debStack.pop();


}


static void printMap() {


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

String temp = "";

for (int j = 0; j < MapSize; j++) {

temp += Visited[i][j];

}

log(temp);

}


}


private static int countOne(int bitmask) {


int count = 0;

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

if ((bitmask & (1 << i)) != 0) {

count++;

} else {


}

}


return count;

}


static int[] rotY = { -1, 0, 1, 0 };

static int[] rotX = { 0, 1, 0, -1 };


public static void log(String input) {

if (Debug) {

System.out.println(input);

}

}


public static void log(String input, Object... args) {

if (Debug) {

System.out.println(String.format(input, args));

}

}


}

'Knowledge > 알고리즘' 카테고리의 다른 글

[스크랩] MD5 (위키백과)  (0) 2018.06.04
백준 3671번: 산업 스파이의 편지  (0) 2017.10.20
백준 14500번: 테트로미노  (0) 2017.10.20
백준 13460번: 째로탈출2  (0) 2017.10.20
백준 12100번: 2048(Easy)  (0) 2017.10.19

import java.io.BufferedReader;

import java.io.File;

import java.io.FileReader;

import java.io.InputStreamReader;

import java.util.HashSet;

import java.util.StringTokenizer;


public class Main {


private static boolean Debug = true;

private static int PrimeCount;

static int[] pocket;

static HashSet<String> primeSet;

private static int NumberLen;

private static int T;


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


BufferedReader br;


if (Debug) {

File f = new File("C:\\Users\\wvimi\\Downloads", "2048.txt");

FileReader reader = new FileReader(f);

br = new BufferedReader(reader);

} else {

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

}

StringTokenizer st;


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

for (T = 0; T < TestLen; T++) {


String NumberStr = br.readLine();

NumberLen = NumberStr.length();

pocket = new int[NumberLen];

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

pocket[i] = NumberStr.charAt(i) - '0';

}


// 탐색 리스트 초기화

primeSet = new HashSet();

findPath(0, "");

primeSet.remove("");


PrimeCount = 0;

for (String item : primeSet) {

// 소수라면 PrimeCount++

isPrime(Integer.parseInt(item));

}


// 소수의 개수 출력

System.out.println(PrimeCount);

}


}


// 소수 판별

private static boolean isPrime(int num) {


// 2 ~ 제곱근까지 검색

int end = (int) Math.sqrt(num);

for (int i = 2; i <= end; i++) {

if (num % i == 0) {

return false;

}

}


// 2보다 작으면 안되!

if (num < 2) {

return false;

}


PrimeCount++;

return true;

}


private static void findPath(int check, String input) {

// 중복되는 경우는 제거

if (primeSet.contains(input)) {

return;

} else {

primeSet.add(input);

}


// 0인 비트를 골라 1로 채운뒤, 문자열을 조립한다.

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


int using = 1 << i;


// 시작은 0을 제외한다.

if (check == 0 && pocket[i] == 0) {

continue;

}


if ((check & using) == 0) {

findPath(check + using, input + pocket[i]);

}


}


}


public static void log(String input) {

if (Debug) {

System.out.println(input);

}

}


public static void log(String input, Object... args) {

if (Debug) {

System.out.println(String.format(input, args));

}

}


}



import java.io.BufferedReader;

import java.io.File;

import java.io.FileReader;

import java.io.InputStreamReader;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.Map.Entry;

import java.util.StringTokenizer;


class Block {


HashMap<Integer, int[][]> shapeList;

int[][] origin;

int[] flag;

ArrayList<Integer> fList;


// 블록에 해당하는 모양 Data를 만들어줍니다.

public Block(int[][] data, int[] flag) {

this.origin = data;

this.flag = flag;


fList = new ArrayList<>();

for (int item : flag) {

fList.add(item);

}


shapeList = new HashMap<>();

createShape();

// printAllShape();

}


// 회전과 대칭에 따른 데이터(모양) 생성

private void createShape() {


int[][] temp = origin;


// 0번 모양

shapeList.put(0, origin);


// 1~3번 모양(90, 180, 270)

for (int i = 1; i <= 3; i++) {

temp = rotate(temp);

if (fList.contains(i)) {

shapeList.put(i, temp);

}

}


// 4번 모양

int[][] rev = null;

if (fList.contains(4)) {

rev = reverse(origin);

shapeList.put(4, rev);

}


temp = rev;

// 5~7번 모양 rev + (90, 180, 270)

if (fList.contains(5)) {

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

temp = rotate(temp);

shapeList.put(i, temp);

}

}


}


// 디버깅을 위한 출력

public void printAllShape() {


int[][] shape;

int ysize, xsize;

for (Entry<Integer, int[][]> entry : shapeList.entrySet()) {


shape = entry.getValue();

ysize = shape.length;

xsize = shape[0].length;


Main.log("[%d]", entry.getKey());


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

String line = "";

for (int j = 0; j < xsize; j++) {

line += String.format("%d ", shape[i][j]);

}

Main.log(line);

}

}


}


// 회전 유틸

private int[][] rotate(int[][] data) {

int ysize = data.length;

int xsize = data[0].length;

int end_index = ysize - 1;


int[][] rData = new int[xsize][];

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

rData[i] = new int[ysize];

for (int j = 0; j < ysize; j++) {

rData[i][j] = data[end_index - j][i];

}

}


return rData;

}


// 대칭 유틸

private int[][] reverse(int[][] data) {

int ysize = data.length;

int xsize = data[0].length;

int end_index = xsize - 1;


int[][] rData = new int[ysize][];

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

rData[i] = new int[xsize];

for (int j = 0; j < xsize; j++) {

rData[i][j] = data[i][end_index - j];

}

}


return rData;

}


}


public class Main {


private static int MapSize_Y;

private static int MapSize_X;

static int[][] Map;


static private ArrayList<Block> bList;


private static boolean Debug = true;

private static int MaxSum;


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


BufferedReader br;


if (Debug) {

File f = new File("C:\\Users\\wvimi\\Downloads", "2048.txt");

FileReader reader = new FileReader(f);

br = new BufferedReader(reader);

} else {

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

}

StringTokenizer st;


// 맵 크기

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

MapSize_Y = Integer.parseInt(st.nextToken());

MapSize_X = Integer.parseInt(st.nextToken());


// 맵 데이터 입력

Map = new int[MapSize_Y][];

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

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

Map[i] = new int[MapSize_X];

for (int j = 0; j < MapSize_X; j++) {

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

}

}


// 블록을 담을 리스트

bList = new ArrayList<>();

Block item; // 블록에는 모양 값들이 저장 된다.


// 블록 모양, 필요한 모양 값 (0: 원형, 1~3: 회전, 4: 대칭, 5~7: 대칭 후 회전)

int[][] 네모Shape = { { 1, 1 }, { 1, 1 } };

item = new Block(네모Shape, new int[] { 0 });

bList.add(item);


int[][] 일자Shape = { { 1, 1, 1, 1 } };

item = new Block(일자Shape, new int[] { 0, 1 });

bList.add(item);


int[][] 산Shape = { { 1, 1, 1 }, { 0, 1, 0 } };

item = new Block(산Shape, new int[] { 0, 1, 2, 3 });

bList.add(item);


int[][] 기역Shape = { { 1, 0 }, { 1, 0 }, { 1, 1 } };

item = new Block(기역Shape, new int[] { 0, 1, 2, 3, 4, 5, 6, 7 });

bList.add(item);


int[][] 어긋Shape = { { 1, 0 }, { 1, 1 }, { 0, 1 } };

item = new Block(어긋Shape, new int[] { 0, 1, 2, 3, 4, 5, 6, 7 });

bList.add(item);


// 완전탐색

MaxSum = -1;

dfs();


// 시간 출력

System.out.println(MaxSum);

}


public static void dfs() {


int blockLen = bList.size();

// 모든 블록에 대한 경우

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

Block block = bList.get(i);


// 각 블록에 따른 데이터를 가져온다. (대칭 및 회전이 포함된 데이터)

for (Entry<Integer, int[][]> item : block.shapeList.entrySet()) {

int[][] data = item.getValue();

int ysize = data.length, xsize = data[0].length;


// 탐색범위 지정(드레그)

int endy, endx;

endy = MapSize_Y - ysize;

endx = MapSize_X - xsize;


// 지정된 탐색 범위에서, data에 맞도록 검색

search(endy, endx, data);

}


}


}


// 해당 블록 모양을 가지고, 해당 위치에서 검색을 해봅니다.

public static void search(int endy, int endx, int[][] data) {


// 탐색 사이즈

int yszie = data.length, xsize = data[0].length;

// 탐색 구간은 (0,0) ~ (endy, endx) 드레그

for (int y = 0; y <= endy; y++) {

for (int x = 0; x <= endx; x++) {


// Block 모양에 따른 탐색

int sum = 0;

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

for (int j = 0; j < xsize; j++) {

if (data[i][j] == 1) { // 탐색

sum += Map[y + i][x + j];

}

}

}


// 최대값 판별

if (MaxSum < sum) {

MaxSum = sum;

}


}

}

// log("합: " + sum);

}


public static void log(String input) {

if (Debug) {

System.out.println(input);

}

}


public static void log(String input, Object... args) {

if (Debug) {

System.out.println(String.format(input, args));

}

}


}



'Knowledge > 알고리즘' 카테고리의 다른 글

1767. [SW Test 샘플문제] 프로세서 연결하기  (0) 2017.10.21
백준 3671번: 산업 스파이의 편지  (0) 2017.10.20
백준 13460번: 째로탈출2  (0) 2017.10.20
백준 12100번: 2048(Easy)  (0) 2017.10.19
백준 3190번: 뱀  (0) 2017.10.19

import java.io.BufferedReader;

import java.io.File;

import java.io.FileReader;

import java.io.InputStreamReader;

import java.util.Stack;

import java.util.StringTokenizer;


class Ball {


int y, x;

static int MapSize_Y;

static int MapSize_X;

static int holeY;

static int holeX;


public Ball(int y, int x) {

this.y = y;

this.x = x;


Main.Map[y][x] = 'X'; // 공의 위치 표기

}


public void move(int rIndex) {


int tempY = y;

int tempX = x;

int moveY = y + Main.rotY[rIndex];

int moveX = x + Main.rotX[rIndex];

// 한 방향으로 직진

while (isRight(moveY, moveX)) {

// 성공좌표를 저장 한다.


y = moveY;

x = moveX;


// 전진

moveY += Main.rotY[rIndex];

moveX += Main.rotX[rIndex];

}


// 공의 위치를 변경한다.

Main.Map[tempY][tempX] = '.';

Main.Map[y][x] = isHoll() ? 'O' : 'X';

}


public void move(int inputY, int inputX) {

Main.Map[this.y][this.x] = isHoll() ? 'O' : '.';

this.y = inputY;

this.x = inputX;

Main.Map[this.y][this.x] = isHoll() ? 'O' : 'X';

}


public boolean isRight(int inputY, int inputX) {


if (inputY < 0 || inputX < 0 || inputY >= MapSize_Y || inputX >= MapSize_X) {

// 배열 밖이라면 No

return false;

} else if (isHoll()) {

// 구멍에 있다면 No

return false;

} else if (Main.Map[inputY][inputX] == 'O') {

// 구멍으로 간다면 Yes

return true;

}


// 빈칸이라면 Yes

return Main.Map[inputY][inputX] == '.';

}


public int getXY() {

return y * MapSize_X + x;

}


public boolean isHoll() {

return Ball.holeX == x && Ball.holeY == y;

}


}


public class Main {


private static boolean Debug = true;


private static final int left = 3, right = 1, up = 0, down = 2;

static int[] rotY = { -1, 0, 1, 0 };

static int[] rotX = { 0, 1, 0, -1 };


private static int MapSize_Y;

private static int MapSize_X;

static char[][] Map;

private static int minFindRed;

static Ball rBall;


private static Ball bBall;


private static int[][] Visited;


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


BufferedReader br;


if (Debug) {

File f = new File("C:\\Users\\wvimi\\Downloads", "2048.txt");

FileReader reader = new FileReader(f);

br = new BufferedReader(reader);

} else {

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

}

StringTokenizer st;


// 맵 크기, 사과 개수

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

MapSize_Y = Integer.parseInt(st.nextToken());

MapSize_X = Integer.parseInt(st.nextToken());

Ball.MapSize_Y = MapSize_Y;

Ball.MapSize_X = MapSize_X;


// 맵 생성

Map = new char[MapSize_Y][];

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

Map[i] = new char[MapSize_X];

String input = br.readLine();

char item;

for (int j = 0; j < MapSize_X; j++) {


// 맵에 기록, Ball 객체 생성

item = input.charAt(j);

switch (item) {

case 'B':

bBall = new Ball(i, j);

Map[i][j] = 'X';

break;

case 'R':

rBall = new Ball(i, j);

Map[i][j] = 'X';

break;

case 'O':

Ball.holeY = i;

Ball.holeX = j;

Map[i][j] = 'O';

break;

default:

Map[i][j] = item;

break;

}

}

}


// 방문배열 생성 [rBall.getXY()][bBall.getXY()]

int vSize = MapSize_X * MapSize_Y;

Visited = new int[vSize][];

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

Visited[i] = new int[vSize];

}


minFindRed = Integer.MAX_VALUE;

// 프레임 체크 (첫 번째 순간은 중복되지 않는다.)

Visited[rBall.getXY()][bBall.getXY()] = 1;


// printMap();

tiltBoard(0);


// 시간 출력

System.out.println(minFindRed == Integer.MAX_VALUE ? -1 : minFindRed);

}


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


private static void tiltBoard(int index) {


if (minFindRed <= index) {

// log("탐색불필요 " + debStack);

return;

} else if (bBall.isHoll()) {

// log("[블루볼] " + debStack);

return;

}


// 1.레드볼 여부 && 2. index == 10

if (rBall.isHoll()) { // && !bBall.isHoll() // 위에서 이미 체크

if (minFindRed > index) {

minFindRed = index;

}

// log("[레드볼]" + debStack.toString());

return;

} else if (index == 10) {

// log("[index 10] " + debStack);

return;

}


int redY = rBall.y;

int redX = rBall.x;

int blueY = bBall.y;

int blueX = bBall.x;

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


// 1. 공을 움직인다.

switch (i) {

case left:

if (redX < blueX) {

rBall.move(i);

bBall.move(i);

} else {

bBall.move(i);

rBall.move(i);

}

break;

case right:

if (redX > blueX) {

rBall.move(i);

bBall.move(i);

} else {

bBall.move(i);

rBall.move(i);

}

break;

case up:

if (redY < blueY) {

rBall.move(i);

bBall.move(i);

} else {

bBall.move(i);

rBall.move(i);

}

break;

case down:

if (redY > blueY) {

rBall.move(i);

bBall.move(i);

} else {

bBall.move(i);

rBall.move(i);

}

break;

}


// 2. 가능한 위치로 이동하여 탐색한다. (좌표 정보는 Ball 객체에 담겨있다.)

// 모두 제자리에 있으면, 탐색X

// 실행됬던 프레임이라면, 탐색X

if (rBall.x == redX && rBall.y == redY && bBall.x == blueX && bBall.y == blueY) {

// non-target

} else if (Visited[rBall.getXY()][bBall.getXY()] == 0) {

Visited[rBall.getXY()][bBall.getXY()] = 1;

// debStack.push(i);


// printMap();

tiltBoard(index + 1);


Visited[rBall.getXY()][bBall.getXY()] = 0;

// debStack.pop();

}


// 3. 공을 원위치로 시킨다.

rBall.move(redY, redX);

bBall.move(blueY, blueX);

}


}


// 디버깅용 프린트 맵

private static void printMap() {


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

String temp = "";

for (int j = 0; j < MapSize_X; j++) {

temp += Map[i][j];

}

if (i == 0) {

temp += "시작";

}

log(temp);

}


}


public static void log(String input) {

if (Debug) {

System.out.println(input);

}

}


public static void log(String input, Object... args) {

if (Debug) {

System.out.println(String.format(input, args));

}

}


}



'Knowledge > 알고리즘' 카테고리의 다른 글

백준 3671번: 산업 스파이의 편지  (0) 2017.10.20
백준 14500번: 테트로미노  (0) 2017.10.20
백준 12100번: 2048(Easy)  (0) 2017.10.19
백준 3190번: 뱀  (0) 2017.10.19
백준 14499번: 주사위 굴리기  (0) 2017.10.19

import java.io.BufferedReader;

import java.io.File;

import java.io.FileReader;

import java.io.InputStreamReader;

import java.util.LinkedList;

import java.util.Queue;

import java.util.StringTokenizer;


public class Main {


private static boolean Debug = true;

private static int MapSize;

private static int[][] OriginMap;

private static int[][] CopyMap;

private static Queue<Integer>[] bQueue;

static int MaxNum = 0;


final static int north = 0, east = 1, south = 2, west = 3;


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


BufferedReader br;


if (Debug) {

File f = new File("C:\\Users\\wvimi\\Downloads", "2048.txt");

FileReader reader = new FileReader(f);

br = new BufferedReader(reader);

} else {

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

}

StringTokenizer st;


// 맵 크기, 사과 개수

MapSize = Integer.parseInt(br.readLine());

MaxNum = 0;


// 맵 생성

OriginMap = new int[MapSize][];

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

OriginMap[i] = new int[MapSize];

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

int item;

for (int j = 0; j < MapSize; j++) {

item = Integer.parseInt(st.nextToken());

OriginMap[i][j] = item;

// 합칠 수 없는 경우, 처음 주어진 수가 가장 크다.

if (MaxNum < item) {

MaxNum = item;

}

}

}


// 큐 초기화 (블록을 옮기는 데 사용된다.

bQueue = new LinkedList[MapSize];

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

bQueue[i] = new LinkedList<>();

}


// 00000 ~ 33333

int[] bitmasking = new int[5];

execute(bitmasking, 0);


// 시간 출력

System.out.println(MaxNum);

}


private static void execute(int[] bitmask, int index) {


// 비트마스킹을 조립

if (index <= 4) {

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

bitmask[index] = i;

execute(bitmask, index + 1);

}

return;

}


// 맵초기화

initMap();


// 실행

int rIndex;

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

rIndex = bitmask[i];

tiltMap(rIndex);

}


}


private static void initMap() {


// Merge를 위한 지도 초기화

CopyMap = new int[MapSize][];

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

CopyMap[i] = new int[MapSize];

for (int j = 0; j < MapSize; j++) {


int num = OriginMap[i][j];

if (num != 0) { // 0은 빈공간

CopyMap[i][j] = num;

} else {

// non-target

}

}

}


}


private static void tiltMap(int rIndex) {

// log("tiltMap(%d)", rIndex);


// 정방향|역방향

// 행기준|열기준

boolean good = (rIndex == west || rIndex == north);

boolean isRow = (rIndex == west || rIndex == east);

// 방향에 따른 병합 및 매칭

int j_start = (good ? 0 : MapSize - 1);

int j_end = (good ? MapSize : -1);

int j_add = (good ? 1 : -1);


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

// 1. 큐에 대입

int j = j_start;

while (j != j_end) {


// 행기준 열기준에 따라 값을 큐에 넣는다. 

int item = isRow ? CopyMap[i][j] : CopyMap[j][i];

if (item != 0) {

bQueue[i].add(item);

// 값을 옮기면, 해당 자리는 빈공간으로 체크

if (isRow) {

CopyMap[i][j] = 0;

} else {

CopyMap[j][i] = 0;

}

}


j += j_add;

}


// 2. 머지

bQueue[i] = mergeBlock(bQueue[i]);


// 3. 맵에 매칭

j = j_start;

while (j != j_end) {

if (!bQueue[i].isEmpty()) {


if (isRow) {

CopyMap[i][j] = bQueue[i].poll();

// log("큐 방출 [%d][%d] = %d", i, j, CopyMap[i][j].num);

} else {

CopyMap[j][i] = bQueue[i].poll();

// log("큐 대입 [%d][%d] = %d", j, i, CopyMap[j][i].num);

}


} else {

break;

}

j += j_add;

}


}


}


static Queue<Integer> rQue;


private static Queue<Integer> mergeBlock(Queue<Integer> que) {


// 반환을 위한 큐

rQue = new LinkedList<>();


// 합치고

int item1 = 0, item2 = 0;

while (true) {


// 합칠 대상1 픽업

if (item1 == 0) {

if (!que.isEmpty()) {

item1 = que.poll();

} else {

// 큐가 비었으므로

break;

}

}


// 합칠 대상2 픽업

if (item2 == 0) {

if (!que.isEmpty()) {

item2 = que.poll();

} else {

// 비교대상이 없으므로

rQue.add(item1);

break;

}

}


// item1과 item2를 합친다.

if (item1 == item2) {


int mergeNum = item1 * 2;

rQue.add(mergeNum);


// 최고값 측정

if (MaxNum < mergeNum) {

MaxNum = mergeNum;

}

item1 = 0;

item2 = 0;

} else { // 합칠수 없는 경우, 이전 비교대상은 rQue에 넣는다.


rQue.add(item1);

item1 = item2; // 다음비교 대상이 첫번 째가 된다.

item2 = 0;

}


}


return rQue;

}


public static void log(String input) {

if (Debug) {

System.out.println(input);

}

}


public static void log(String input, Object... args) {

if (Debug) {

System.out.println(String.format(input, args));

}

}


}



'Knowledge > 알고리즘' 카테고리의 다른 글

백준 14500번: 테트로미노  (0) 2017.10.20
백준 13460번: 째로탈출2  (0) 2017.10.20
백준 3190번: 뱀  (0) 2017.10.19
백준 14499번: 주사위 굴리기  (0) 2017.10.19
백준 14502번: 연구소  (0) 2017.10.17

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.util.Hashtable;

import java.util.LinkedList;

import java.util.Queue;

import java.util.StringTokenizer;


class Snake {

Queue<Integer> body = new LinkedList<>();


// 해당 위치로 움직인다.

void move(int where, boolean hasApple) {

if (hasApple) {

body.add(where);

} else {

body.poll();

body.add(where);

}

}


// 자기 자신에 충돌하는지 체크한다.

boolean isSelf(int where) {

return body.contains(where);

}

}


public class Main {


private static boolean Debug = false;

private static int MapSize;

private static int[][] Map;

private static Hashtable<Integer, Character> comMap;

private static Snake snake = new Snake();


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


BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

StringTokenizer st;


// 맵 크기, 사과 개수

MapSize = Integer.parseInt(br.readLine());

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


// 맵 생성

Map = new int[MapSize][];

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

Map[i] = new int[MapSize];

}


// 사과 위치 배정

int y, x;

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

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

y = Integer.parseInt(st.nextToken()) - 1;

x = Integer.parseInt(st.nextToken()) - 1;

Map[y][x] = 1;

}


// 커맨드 읽기

comMap = new Hashtable();

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

int time;

char direct;

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

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

time = Integer.parseInt(st.nextToken());

direct = st.nextToken().charAt(0);

comMap.put(time, direct);

}


// 위치 초기화, 시간 초기화

y = x = 0;

rIndex = 1;

timer = 0;


// 뱀이 움직인다.

snake.move(0, false);

findPath();


// 시간 출력

System.out.println(timer);

}


static int[] rotY = { -1, 0, 1, 0 };

static int[] rotX = { 0, 1, 0, -1 };


static int y, x;

static int rIndex;

static int timer;


private static void findPath() {


// 해당 시간에 방향 전환이 발생하는가?

if (comMap.containsKey(timer)) {

char direct = comMap.get(timer);


// 왼쪽 회전 =>  rIndex--;  // 오른쪽 회전 => rIndex++;

if (direct == 'L') {

rIndex = rIndex == 0 ? 3 : rIndex - 1;

} else {

rIndex = rIndex == 3 ? 0 : rIndex + 1;

}

comMap.remove(timer);

}


// 움직임이 시작되는 순간

timer++;


// 움직이려는 방향이 맞다면 움직인다.

if (isVaild(rIndex)) {


y += rotY[rIndex];

x += rotX[rIndex];


int where = y * MapSize + x;

// 자신의 몸에 충돌하는가?

if (snake.isSelf(where)) {

return;

}


// 사과가 있다면

if (Map[y][x] == 1) {

Map[y][x] = 0;

snake.move(where, true);

} else { // 사과가 없다면

snake.move(where, false);

}


findPath();

} else {

// 움직이는 방향이 맵 밖인 경우, 이탈한다.

return;

}


}


// 해당 방향이 맵의 범위를 초과하는지를 판단한다.

private static boolean isVaild(int index) {


switch (index) {

case 0:

return y - 1 >= 0;

case 2:

return y + 1 < MapSize;

case 1:

return x + 1 < MapSize;

case 3:

return x - 1 >= 0;

}


return false;

}


public static void log(String input) {

if (Debug) {

System.out.println(input);

}

}


public static void log(String input, Object... args) {

if (Debug) {

System.out.println(String.format(input, args));

}

}


}



'Knowledge > 알고리즘' 카테고리의 다른 글

백준 13460번: 째로탈출2  (0) 2017.10.20
백준 12100번: 2048(Easy)  (0) 2017.10.19
백준 14499번: 주사위 굴리기  (0) 2017.10.19
백준 14502번: 연구소  (0) 2017.10.17
백준 14501번: 퇴사  (0) 2017.10.17

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.util.StringTokenizer;


class Dice {

private int[] face;


static final int Left = 1, Right = 2;

static final int Up = 3, Down = 4;


int top, bottom;

int north, south;

int west, east;


// 전개도를 펼쳤을 때, 가운데를 top이라 생각하고, 각각의 면에 index를 메김

public Dice() {

top = 1;

bottom = 6;

north = 2;

south = 5;

west = 4;

east = 3;


face = new int[7];

}


// 주사위 디버깅

private void printDice() {

Main.log("%2d%2d%2d", 0, north, 0);

Main.log("%2d%2d%2d", west, top, east);

Main.log("%2d%2d%2d", 0, south, 0);

Main.log("%2d%2d%2d", 0, bottom, 0);

}


// 주사위를 해당 방향에 굴린 후, 바닥면을 주사위로 옮긴다.

public int move(int direct, int num) {


// 주사위를 굴리면 전개도에서 4면의 변화가 생김

int temp;

switch (direct) {

case Up:

temp = north;

north = top;

top = south;

south = bottom;

bottom = temp;

break;

case Down:

temp = bottom;

bottom = south;

south = top;

top = north;

north = temp;

break;

case Left:

temp = west;

west = top;

top = east;

east = bottom;

bottom = temp;

break;

case Right:

temp = east;

east = top;

top = west;

west = bottom;

bottom = temp;

break;

}


// 윗면 출력

System.out.println(face[top]);

// printDice();


// 주사위 면 복사

int result;

result = face[bottom];

if (num != 0) {

face[bottom] = num;

}


return result;

}


}


public class Main {


private static boolean Debug = false;

private static int MapSize_Y;

private static int MapSize_X;

private static int[][] Map;

private static int[] Command;

private static Dice Dice;

private static int startY;

private static int startX;


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


BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

StringTokenizer st;


// 맵 크기

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

MapSize_Y = Integer.parseInt(st.nextToken());

MapSize_X = Integer.parseInt(st.nextToken());


// 주사위 시작 위치

startY = Integer.parseInt(st.nextToken());

startX = Integer.parseInt(st.nextToken());

Command = new int[Integer.parseInt(st.nextToken())];


// 맵 읽기

Map = new int[MapSize_Y][];

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

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

Map[i] = new int[MapSize_X];

for (int j = 0; j < MapSize_X; j++) {

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

}

}


// 커맨드 읽기

int clen = Command.length;

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

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

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

}


Dice = new Dice();


MoveDice();

// System.out.println(MaxSafeCount);

}


// 1~4 동서북남

static int[] rotY = { 0, 0, 0, -1, 1 };

static int[] rotX = { 0, 1, -1, 0, 0 };


private static void MoveDice() {


int clen = Command.length;

int y = startY;

int x = startX;


int moveY, moveX;


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

int direct = Command[i];

moveY = y + rotY[direct];

moveX = x + rotX[direct];


if (!isRight(moveY, moveX)) {

continue;

}


// 바닥면의 경우

int mapValue = Map[moveY][moveX];

if (mapValue != 0) {

// 바닥에 0이 아닐때, 숫자는 주사위로 옮겨간다.

Dice.move(direct, mapValue);

Map[moveY][moveX] = 0;

} else {

// 바닥이 0이라면 , 숫자는 맵으로 옮겨간다.

int num = Dice.move(direct, mapValue);

Map[moveY][moveX] = num;

}


y = moveY;

x = moveX;

}

}


private static boolean isRight(int y, int x) {


if (x < 0 || y < 0 || x >= MapSize_X || y >= MapSize_Y) {

return false;

} else {

return true;

}

}


public static void log(String input) {

if (Debug) {

System.out.println(input);

}

}


public static void log(String input, Object... args) {

if (Debug) {

System.out.println(String.format(input, args));

}

}


}



'Knowledge > 알고리즘' 카테고리의 다른 글

백준 12100번: 2048(Easy)  (0) 2017.10.19
백준 3190번: 뱀  (0) 2017.10.19
백준 14502번: 연구소  (0) 2017.10.17
백준 14501번: 퇴사  (0) 2017.10.17
백준 13458번: 시험 감독  (0) 2017.10.17

+ Recent posts