코드굽는 타자기

SWEA[4615] - 재미있는 오셀로 게임[D3] 본문

알고리즘/Simulation

SWEA[4615] - 재미있는 오셀로 게임[D3]

bright-jun 2020. 2. 8. 21:56

링크

SWEA[4615]

문제설명

  • 시뮬

문제풀이

  • 시뮬
  • 무조건 뒤집으면서 가면 안됨
    • 못뒤집는 경우가 있음.

문제코드

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Solution {
    public static int[][] dir = {    //8방향 12시부터 시계방향
            {-1,0},
            {-1,1},
            {0,1},
            {1,1},
            {1,0},
            {1,-1},
            {0,-1},
            {-1,-1}
    };
    public static int[][] map;
    public static int N;
    public static boolean flipable(int r, int c,int dir_, int color) {
        int nr=0;
        int nc=0;
        for (int i = 0; i < N-1; i++) {    //암만 많이가봤자 N-1만큼밖에 못감
            nr = r + dir[dir_][0];
            nc = c + dir[dir_][1];
            if(nr>=0 && nr<N && nc>=0 && nc<N) {    //경계안에서
//                직선탐색중 끝까지 뒤집을 수 있도록해주는 돌이 없을 수 있음(벽을 만나거나, 빈칸이거나, 계속 다른색이거나)
                if(map[nr][nc]==color) {    //뒤집게 해 줄 돌을 찾았음
                    return true;
                }
                else if(map[nr][nc]==0) {    //빈칸 일 경우
                    return false;
                }
                else {    //다른 색일 경우
//                    한칸이동
                    r = nr;
                    c = nc;
                }
            }
            else {    //경계 밖일 경우
                return false;
            }
        }
//        뒤집을게없음
        return false;
    }
    public static void flip(int r, int c, int dir_, int color) {
//        이 방향으로는 뒤집으면서 가면 된다.
        int nr=0;
        int nc=0;
        for (int i = 0; i < N-1; i++) {    //암만 많이가봤자 N-1만큼밖에 못감
            nr = r + dir[dir_][0];
            nc = c + dir[dir_][1];
            if(map[nr][nc]==color) {    //뒤집게 해 줄 돌을 찾았음
                return;
            }
            else {    //다른 색일 경우
//                    색 바꾸고
                map[nr][nc]=color;
//                    한칸이동
                r = nr;
                c = nc;
            }
        }
    }
    public static void put(int r,int c,int color) {
//        돌 놓기
        map[r][c]=color;
//        8방향으로 돌이 갈 수 있는지 없는지 탐색
        for (int i = 0; i < 8; i++) {
//            1칸 탐색중 경계안에 있고, 빈칸이아니며, 다른색인 경우 직선탐색 시작한다.
//            직선탐색중 끝까지 뒤집을 수 있도록해주는 돌이 없을 수 있음(벽을 만나거나, 빈칸이거나, 계속 다른색이거나)
//            이러면 뒤집으면서가면 다시 되돌려줘야함. 미리 체크하고 뒤집기
            if(flipable(r,c,i,color)) {
                flip(r,c,i,color);
            }
        }
    }
    public static void main(String[] args) throws IOException {
        //System.setIn(new FileInputStream("res/swea/4615.txt"));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        int T=Integer.parseInt(br.readLine());
        for (int test_case = 1; test_case <= T; test_case++) {
            int W=0;
            int B=0;
//            입력
            st = new StringTokenizer(br.readLine().trim()," ");
            N = Integer.parseInt(st.nextToken());
            map = new int[N][N];
            int M = Integer.parseInt(st.nextToken());
            int[][] oper = new int[M][3];    //{c(y) , r(x), color}
            for (int i = 0; i < M; i++) {
                st = new StringTokenizer(br.readLine().trim()," ");
                for (int j = 0; j < 3; j++) {
                    oper[i][j] = Integer.parseInt(st.nextToken());
                }
            }
//            {1:흑, 2:백}
//            말 초기판 설정
            map[(N/2)-1][(N/2)-1]=2;
            map[(N/2)-1][(N/2)-1+1]=1;
            map[(N/2)-1+1][(N/2)-1]=1;
            map[(N/2)-1+1][(N/2)-1+1]=2;

//            돌 놓기
            for (int i = 0; i < M; i++) {
                put(oper[i][1]-1,oper[i][0]-1,oper[i][2]);
            }

//            돌 세기
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    if(map[i][j]==2) {
                        W++;
                    }
                    else if(map[i][j]==1) {
                        B++;
                    }
                }
            }
            System.out.println("#"+test_case+" "+B+" "+W);
            /*
             * 초기화
             */
        }//end test_case
    }//end main
}

틀렸던 문제코드

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.Buffer;
import java.util.Arrays;
import java.util.Scanner;
import java.util.StringTokenizer;

public class Solution {
    /*
     * 흑:1 백:2
     */
    static int[][] map = new int [9][9];
    static int N;
    static int M;
    public static int[][] dir = {    //8방향 탐색
            {-1,0},
            {-1,1},
            {0,1},
            {1,1},
            {1,0},
            {1,-1},
            {0,-1},
            {-1,-1}
    };

    /*
     * 그 방향으로 체크하고 뒤집는다
     */
    public static void flip(int r, int c, int color, int dir_) {
        //dir_ 방향으로 다음이 지금과 다른 색상임.
        int sr = r;    //시작
        int sc = c;
        int nr = 0;    //다음
        int nc = 0;
        int fr = 0;    //마지막
        int fc = 0;
        int cnt = 0;
        while(true) {
            nr = sr+dir[dir_][0];
            nc = sc+dir[dir_][1];
            if(nr>=1 && nr<=N && nc>=1 && nc<=N) {    //경계 내에서
                if(map[nr][nc]!= color) {    //뒤집어야 할 애
                    sr=nr;
                    sc=nc;
                    cnt++;
                }
                else if (map[nr][nc]== 0) {    //없음, 벽
                    return;
                }
                else {    //여기까지 뒤집어야 함.
                    fr=nr;
                    fc=nc;
                    break;
                }
            }
            else {    //벽
                return;
            }
        }
        for (int i = 1; i <= cnt; i++) {
            nr = r+i*dir[dir_][0];
            nc = c+i*dir[dir_][1];
            map[nr][nc]=color;
        }
}
    public static void main(String[] args) throws NumberFormatException, IOException {
        //System.setIn(new FileInputStream("res/swea/4615.txt"));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int T=Integer.parseInt(br.readLine().trim());
        for (int test_case = 1; test_case <= T; test_case++) {
            StringTokenizer st = new StringTokenizer(br.readLine().trim(), " ");
            N=Integer.parseInt(st.nextToken());
            M=Integer.parseInt(st.nextToken());

            map[N/2][N/2] = 2;
            map[N/2+1][N/2] = 1;
            map[N/2][N/2+1] = 1;
            map[N/2+1][N/2+1] = 2;

            int [][] oper = new int[M][3];

            for (int i = 0; i < M; i++) {
                st = new StringTokenizer(br.readLine().trim(), " ");
                for (int j = 0; j < 3; j++) {
                    oper[i][j] = Integer.parseInt(st.nextToken());
                }
            }
            int r=0;
            int c=0;
            int color=0;
            int nr=0;
            int nc=0;
            for (int i = 0; i < M; i++) {
                /*put*/
                r=oper[i][1];
                c=oper[i][0];
                color=oper[i][2];
                map[r][c] = color;
                /*dir_check*/
                for (int dir_ = 0; dir_ < 8; dir_++) {
                    nr = r+dir[dir_][0];
                    nc = c+dir[dir_][1];

                    if(nr>=1 && nr<=N && nc>=1 && nc<=N) {    //경계 안에서
                        if(map[nr][nc]==color || map[nr][nc]==0) {    //체크할 필요 없음
                            continue;
                        }
                        else {    //뒤에 그 색이 또 나오면 뒤집기 가능
                            flip(r,c,color,dir_);
                        }
                    }
                    else {    //경계 밖인 경우
                        continue;
                    }
                }
            }

            int B=0;
            int W=0;
            for (int i = 1; i <= N; i++) {
                for (int j = 1; j <= N; j++) {
                    if(map[i][j]==1) {
                        B++;
                    }
                    else if(map[i][j]==2) {
                        W++;
                    }
                }            
            }


            System.out.println("#"+test_case+" "+B+" "+W);
            /*
             * 초기화
             */ 
            for (int i = 0; i < 8; i++) {
                for (int j = 0; j < 8; j++) {
                    map[i][j]=0;
                }
            }
            N=0;
            M=0;
        }//end test_case
    }//end main
}//end class

아쉬운점

  • 왜틀렸는지 모르겠음
  • 테케가 좀 많았으면좋겠음

잘한점

  • 왜맞았는지 모르겠음 논리는 똑같이 해서 썼는데...

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

SWEA[1873] - 상호의 배틀필드[D3]  (0) 2020.02.12
SWEA[4014] - 활주로 건설  (0) 2020.02.09
SWEA[5653] - 줄기세포배양  (0) 2020.02.08
SWEA[5644] - 무선 충전기  (1) 2020.02.06
SWEA[1954] - 달팽이 숫자[D2]  (0) 2020.01.21
Comments