Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 158 additions & 2 deletions src/week6/monkeyWhoWannabeHorse1600/Main.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,160 @@
package week6.monkeyWhoWannabeHorse1600;

public class Main {
}
import java.util.ArrayDeque;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main{

static class Info {
int r;
int c;
int hores; //말로 이동할 수 있는 남은 기회
int move ; //움직인 횟수

public Info(int r, int c, int hores,int move) {
this.r=r;
this.c=c;
this.hores=hores;
this.move=move;
}
}
static int [][]map;

static int K;
static int R,C;


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

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
K = Integer.parseInt(br.readLine());

StringTokenizer st = new StringTokenizer(br.readLine());
C =Integer.parseInt(st.nextToken());
R = Integer.parseInt(st.nextToken());

map = new int[R][C];

for(int i = 0 ; i <R ;i++){
st = new StringTokenizer(br.readLine());
for(int j = 0 ; j<C;j++){

int n = Integer.parseInt(st.nextToken());
if(n==1){ //장애물일때
map[i][j] = Integer.MAX_VALUE;
}else {
//평지일때 -1로 초기화. -> 그 이유는 map에 남은 말처럼 이동할 수 있는 남은 횟수를 저장할꺼기 때문 따라서 0값도 올 수 있기때문에 -1로 초기화.
map[i][j] = -1;
}
}
}



System.out.println(bfs(new Info(0,0,K,0)));



}

private static int bfs (Info info) {


int [] dr = {0,0,1,-1};
int [] dc = {1,-1,0,0};


int [] hr = {-1, 1, -1, 1, -2, 2, -2, 2};
int [] hc = {-2, -2, 2, 2, -1, -1, 1, 1};

Queue<Info> queue = new ArrayDeque<>();
queue.add(info);

if (R == 1 && C== 1) return 0;

while (!queue.isEmpty()) {

Info current_Info = queue.poll();


int curR = current_Info.r;
int curC = current_Info.c;
int nextMove = current_Info.move +1;
int curHourse = current_Info.hores;


//상 하 좌 우 인접이동
for(int i = 0 ; i <4 ; i++){

int nr = curR + dr[i];
int nc = curC + dc[i];

//2차원 배열의 범위를 넘어가는 경우는 넘겨준다.
if (!isRange(nr, nc) )continue;

//남은 말처럼 이동할 수 있는 횟수가 map[nr][nc]보다 큰 경우
//이 조건을 한 이유는
// 예를 들어 어떠한 좌표에 원숭이가 도착했다고 치자. (3,2)좌표라고 해보겠다.
// 이 좌표에 처음 도착했을때 move값이 그 칸에 갈 수 있는 가장 최소의 값일 것이다.
// 이때 남은 말의 회수가 1이였다고 치고 map[3][2]=1을 저장하였다.
//또 어떠한 경로로 인해 map[3][2]에 올 수 있는 경우가 있다. 이때 move값은 처음도착했을때의 값보다 클 것이다.
//하지만 map[nr][nc]=1이였을 때 , 이 걸로 도착지(정답)에 도착한다는 보장이 없다.
//따라서 map[nr][nc] <curHourse 말로이동할 수 있는더 큰 경우가 존재한다면 그 경우에도 탐색을 해 주어야하기때문에 이 조건문을 썼다.
if(map[nr][nc]<curHourse){

//도착지에 도착했다면 이동 횟수를 리턴한다.
//큐에서 꺼낸 Info의 move값은 최소값으로 수 밖에 없다.
//큐에 move가 1일때,2일때,3일때 순으로 차례로 저장되기 때문이다.
if(nr==R-1 && nc ==C-1){
return nextMove;
}
//map에 남은 말처럼 이동 할 수 있는 횟수를 저장한다.
map[nr][nc] = curHourse;
queue.add(new Info(nr, nc, curHourse, nextMove));

}

}


//말처럼 이동 하는 경우
// 남은 횟수가 0보다 커야한다.
if(current_Info.hores>0){
//말로 이동하는 거니까 횟수를 하나 감소시킨다.
curHourse --;
//말로 이동
for(int i = 0 ; i < 8 ; i++){

int nr = curR + hr[i];
int nc = curC + hc[i];


if (!isRange(nr, nc))continue;

if(map[nr][nc]<curHourse){
if(nr==R-1 && nc ==C-1){

return nextMove;
}

map[nr][nc] = curHourse;
queue.add(new Info(nr, nc, curHourse, nextMove));
}
}

}


}
return -1;
}

private static boolean isRange (int r,int c){
return r>=0 && r<R && c>=0 && c<C;
}
}
69 changes: 67 additions & 2 deletions src/week8/BJ1034Lamp/Main.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,69 @@
package week8.BJ1034Lamp;

public class Main {
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main{


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

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());


int N = Integer.parseInt(st.nextToken()); //행
int M = Integer.parseInt(st.nextToken()); //열


int [] offCount = new int[N]; // 그 행에 몇의 램프가 꺼져있는지 저장할 배열
String [] line = new String[N]; // 그 행의 램프 상태 => ex )'1010110'

for(int i = 0 ; i < N ; i++){
String s = br.readLine();
int zero = 0 ; // 꺼져있는 램프 개수
for(int j = 0 ; j < M ; j++){
if(s.charAt(j)=='0'){ //램프가 꺼져있다면
zero++;
}
}
//행에 몇개의 램프가 꺼져있는지에 대해 저장한다.
offCount [i]=zero;
//해당 행의 문자열을 저장한다.
//그 이유는 밑에 과정에서 한 행을 완성된 행(모든 램프가 켜져있는)으로 만들 수 있었을때 다른 행들이 현재 행과 똑같은 형태인지 파악하기 위함이다. -> 똑같다면 그 행은 완벽한 행으로 만들 수 있기때문
line[i]=s;
}

int K = Integer.parseInt(br.readLine()); // 스위치를 눌러야 하는 횟수

int max = 0; //최소의 경우는 0

/* 하나의 행에 대하여 완벽한행이 될 수 있다면 다른 행들중에서 같은 경우가 있는지 세어준다. -> 같은 행들도 완벽한 행일 수 밖에 없기때문 */
for(int i = 0 ; i < N; i++){

//첫번째로 ,꺼져있는 램프의 개수 , 즉 스위치를 눌러야하는 횟수가 K보다 크면 안된다. 문제 조건에서 K번을 누르라고 했기 때문
//두번째로 , K-offCount[i] = 더 눌러야 하는 횟수 , 는 짝수여야한다. 짝수여야만 현재상태와 똑같이 만들 수 있기때문이다. 두 번 누르면 원래 상태인것처럼.
if(offCount[i]<=K&&(K-offCount[i])%2==0){

int equalCount = 1 ; // 현재 i은 완벽한 행이므로 초기값은 1

for(int j = 0 ; j < N;j++){
if(i==j)continue; //자기 자신 탐색하는건 넘어간다.
if(line[i].equals(line[j])){ // i 행과 같은 상황의 행이 있다면 +1
equalCount++;
}
}

max=Math.max(max,equalCount); //최대값 갱신
}


}

System.out.println(max); // 정답 출력

}

}