[java]오목 - 백준2615
문제
풀이
문제 해석을 하자면,
- 바둑판에 바둑알을 입력으로 주어지면 “오목게임” 결과를 구하라.
풀이
- 방향을 4가지로 생각해야한다. -> 오른쪽, 대각선 아래, 아래, 대각선 위
- 이를 통해서 정답좌표도 바로 구할 수 있다.
- 그리고 “육목”인지 판단이 중요하다.
- 오목 시작점과 끝쪽에 “바둑알 더 있나 확인”
- 반례조심 : 현재 6목일때 좌표 한칸 이동후에 다시 확인할때 5목으로 판별나서 문제가 발생
코드
public static int[][] inArr = new int[22][22];
public static Pair[] outArr = new Pair[10];
public static int[] dx = {0,1,1,-1}; // 오른쪽, 대각선 아래, 아래, 대각선 위
public static int[] dy = {1,1,0,1};
public static int[] rdx = {0,-1,-1,1}; // reverse
public static int[] rdy = {-1,-1,0,-1};
public static int result, ansX, ansY;
public static int N = 19;
public static boolean endCheck = false;
public static void dfs(int depth, int dir, int cx, int cy) {
//base condition
if(depth == 4) {
// 육목인지만 추가 판단후 "오목확정" 지으면 된다. -> 끝과 처음쪽 둘다 바둑알 더 있나 확인
int nx = cx+dx[dir];
int ny = cy+dy[dir];
int px = outArr[0].x+rdx[dir];
int py = outArr[0].y+rdy[dir];
int nxtCheck = 0;
int preCheck = 0;
if(nx<0||ny<0||nx>=N||ny>=N) {
nxtCheck = 1;
}
if(px<0||py<0||px>=N||py>=N) {
preCheck = 1;
}
if(nxtCheck == 1 && preCheck == 1) {
// 앞, 뒤 둘다 범위 초과라 "오목"확정
result = outArr[depth].val; // 해당 바둑색깔 기록
endCheck=true;
}
if(nxtCheck == 0) {
// 뒤가 범위 초과 아닐때, 육목인지 체크
if(inArr[nx][ny]==outArr[depth].val) {
result = 0; endCheck = false;
return; // 이미 "육목"이라 가망없음
}else {
result = outArr[depth].val; // 해당 바둑색깔 기록
endCheck = true;
}
}
if(preCheck == 0) {
// 앞이 범위 초과 아닐때, 육목인지 체크
if(inArr[px][py]==outArr[depth].val) {
result = 0; endCheck = false;
return; // 이미 "육목"이라 가망없음
}else {
result = outArr[depth].val; // 해당 바둑색깔 기록
endCheck = true;
}
}
return;
}
//recursion
int nx = cx+dx[dir];
int ny = cy+dy[dir];
if(nx<0||ny<0||nx>=N||ny>=N) return;
if(outArr[depth].val == 0) return;
if(outArr[depth].val != inArr[nx][ny]) return;
outArr[depth+1]=new Pair(nx,ny,inArr[nx][ny]);
dfs(depth+1, dir, nx, ny);
}
public static void main(String[] args) throws Exception {
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//input
for(int i=0; i<N; i++) {
StringTokenizer stk = new StringTokenizer(br.readLine(), " ");
for(int j=0; j<N; j++) {
inArr[i][j] = Integer.parseInt(stk.nextToken());
}
}
//run
loop: for(int i=0; i<N; i++) {
for(int j=0; j<N; j++) {
if(inArr[i][j]==0) continue;
outArr[0] = new Pair(i,j,inArr[i][j]);
for(int k=0; k<4; k++) {
dfs(0, k, i, j);
if(endCheck) {
ansX = i; ansY = j; break; // 4방향의 첫 시작점이 정답좌표
}
}
if(endCheck) break loop;
}
}
//output
if(result != 0)
sb.append(result).append("\n").append(ansX+1).append(" ").append(ansY+1);
else
sb.append(result).append("\n");
System.out.print(sb);
}
static class Pair {
int x; int y; int val;
public Pair(int x, int y, int val) {
this.x=x; this.y=y; this.val=val;
}
}
느낀점
재귀가 아닌 for문으로 풀었으면 더 간단했을것 같다..
여러 반례들 추가
/*
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 2 0 0 2 2 2 1 0 0 0 0 0 0 0 0 0 0
0 0 1 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 2 2 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1
7 3
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 2 0 0 2 2 2 1 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 2 2 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1
4 3
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 2 0 0 2 2 2 1 0 0 0 0 0 0 0 0 0 0
0 0 1 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 2 2 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 2 1 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2
0
*/
댓글남기기