ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JAVA] 4013번 : 특이한 자석 (SWEA) & 14891번 : 톱니바퀴 (BOJ)
    Java 2024. 5. 11. 13:29

    입출력 형식만 다르고 사실상 같은 문제라서 같이 적어보는 졸린김에 잠깰겸 적는 풀이 히힛

    https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWIeV9sKkcoDFAVH

     

    SW Expert Academy

    SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

    swexpertacademy.com

    처음에 제출했을 때는 계속 터져버렸다

    그리고 이후에 답을 그냥 보고 이해하는 식으로 풀었다.

    사실 답 보고 금방 이해했다. 그냥 머릿속에 있는걸 코드로 표현을 못하는게 문제였기 때문이다...

    https://kwangkyun-world.tistory.com/entry/Java%EC%9E%90%EB%B0%94-swea-4013-%ED%8A%B9%EC%9D%B4%ED%95%9C-%EC%9E%90%EC%84%9D

     

    [Java/자바 swea 4013] 특이한 자석

    풀이 처음 스택을 쓰려고 했는데 엄청 복잡했습니다... 그래서 2차원 배열을 통해 구현했습니다. map 4x8 2차원 형태로 저장하구 , arr에 시계면 1, 반시계면 -1, 회전 하지않는다면 0 으로 담았습니다

    kwangkyun-world.tistory.com

     

    1. solve 함수

    방향 배열에 각 상태에 따라 방향을 담는다. 

    방향을 담아야 해당 방향에 맞게 자석을 돌리기 때문!

     

    그림을 보면 idx 를 1에서 시작한다면 현재 자석은 3, 다음 자석은 7번이랑 비교하게 된다. (idx 를 0에서 시작한다면 현재 자석은 2, 다음 자석은 6이겠죵) 

    static void solve(int x, int d) {
    		dArr[x] = d; // 받아온 방향 
    		
    		// 오른쪽으로 회전
    		for(int i=x+1;i<4;i++) {
    			if(map[i][6]==map[i-1][2]) {
    				break;
    			}
    			else dArr[i] = -dArr[i-1];
    		}
    		
    		// 왼쪽으로 회전 
    		for(int i=x-1;i>=0;i--) {
    			if(map[i][2]==map[i+1][6]) {
    				break;
    			}
    			else dArr[i] = -dArr[i+1];
    		}
    		
    		rotation();
    	}

     

    처음에 내가 생각했던건 배열을 담아야지 보다는 그냥 변수로 두고 함수로 빼려고 했다.

    // 처음 : 화살표 위치
        static void solve(int x, int d){
    
            // S극 : 1
            // N극 : 0
            // 시계 : 1, 반시계 : -1
    
            // idx : 3이랑 7 이랑 물려 있음
            // 1. idx 에 물려 있는 값 먼저 확인
            // x 랑 x+1
            // 2. 값이 다르면 서로 다른 극
            // 3. 서로 반대 방향 으로 회전
            boolean res[] = new boolean[4];
            for(int i=1;i<=3;i++) {
                // 다른 지 같은 지 결과 배열에 저장
                // 1, 2 (3, 7)
                // 2, 3 (3, 7)
                // 3, 4 (3, 7)
                if(map[i][3]!=map[i+1][7]) {
                    res[i] = true; // 다르면 true
                }else {
                    res[i] = false; // 같으면 false
                }
            }
            // 나 기준 전, 후 확인
            // 다음 꺼랑 비교 할때 -> 내가 3 다음 꺼가 7
            // 이전 꺼랑 비교 할때 -> 내가 7 이전 꺼가 3
            // 다르면 그때
            if(x==1) {
                if(res[x]) {
                    rotation(x, d);
                    rotation(x+1, -d);
                    if(res[x+1]) {
                        rotation(x+2, d);
                        if(res[x+2]) {
                            rotation(x+3, -d);
                        }
                    }
                }
            }else if(x==2) {
                if(res[x-1]) { // 1
                    rotation(x-1, -d);
                    rotation(x, d);
                    if(res[x]) { // 2
                        rotation(x+1, -d);
                        if(res[x+1]) { // 3
                            rotation(x+2, d);
                        }
                    }
                }
            }else if(x==3) {
                if(res[x-1]) {
                    rotation(x-1, -d);
                    rotation(x, d);
                    if(res[x-2]) {
                        rotation(x-2, d);
                    }
                    if(res[x]) {
                        rotation(x+1, -d);
                    }
                }
            }else {
                if(res[x-1]) {
                    rotation(x-1, -d);
                    rotation(x, d);
                    if(res[x-2]) {
                        rotation(x-2, -d);
                        if(res[x-3]) {
                            rotation(x-3, d);
                        }
                    }
                }
            }
        }

     

    이렇게 아주 비효율적인 만약에 코드를 생각했었다 바보.

     

    2. rotation 함수

    // 회전 
    	static void rotation() {
    		for(int i=0;i<4;i++) {
    			if(dArr[i]==0) continue;
    			else if(dArr[i]==1) {
    				// 시계 방향 회전
    				int tmp = map[i][7];
    				
    				for(int y=7;y>=1;y--) {
    					map[i][y] = map[i][y-1];
    				}
    				
    				map[i][0]=tmp;
    			}else if(dArr[i]==-1){ // -1 
    				// 반시계 방향 회전
    				int tmp = map[i][0];
    				
    				for(int y=0;y<=6;y++) {
    					map[i][y] = map[i][y+1];
    				}
    				
    				map[i][7]=tmp;
    			}
    		}
    	}

     

    그리고 회전하는것도 코드를 잘못 작성했었는데, 이전꺼를 다음꺼에 넣거나 다음꺼를 현재꺼에 넣어야하는데, 난 반대로 했었다. 아래처럼....하면 기존 값을 넣는게 아니라 이미 바뀌어진 값을 넣는거라 그냥 값이 이상하게 나온다. 

    // map 회전
        static void rotation(int x, int d) {
            // x : 행 번호
            // 시계
            if(d==1) {
                // 1. 마지막 값을 tmp 에 저장
                int tmp = map[x][8];
                // 2. 한 칸 식 오른쪽
                for(int y=1;y<=7;y++) {
                    map[x][y+1] = map[x][y];
                }
                // 3. tmp 에 저장한 값 처음에 다시 저장
                map[x][1] = tmp;
            }else { // 반시계
                // 반시계
                // 1. 처음 값을 tmp 에 저장
                int tmp = map[x][1];
                // 2. 한 칸 씩 왼쪽
                for(int y=8;y>=2;y--) {
                    map[x][y-1] = map[x][y];
                }
                // 3. tmp 에 저장한 값 마지막에 다시 저장
                map[x][8] = tmp;
            }

     

    쨋든 이 2개의 함수를 이용하면 쉽게 답을 구할수있었다!

    그냥 방향 배열에 방향 담고 그 방향에 맞게 배열을 돌려주기만 하면 되는 문제! 전체 코드는 아래와 같다! 

    import java.io.*;
    import java.util.*;
    
    public class Solution {
    	
    	static int k, map[][], n, dir, dArr[], ans=0;
    	
    	public static void main(String[] args) throws Exception, IOException {
    		
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    		StringTokenizer st;
    		
    		int T = Integer.parseInt(br.readLine());
    
    		for(int tc=1; tc<=T; tc++) {
    			st = new StringTokenizer(br.readLine());
    			k = Integer.parseInt(st.nextToken());
    			
    			map = new int[4][8];
    			ans = 0;
    			
    			for(int i=0;i<4;i++) {
    				st = new StringTokenizer(br.readLine());
    				for(int j=0;j<8;j++) {
    					map[i][j] = Integer.parseInt(st.nextToken());
    				}
    			}
    			
    			for(int i=0;i<k;i++) {
    				dArr = new int[4]; // 방향 배열
    				st = new StringTokenizer(br.readLine());
    				n = Integer.parseInt(st.nextToken());
    				dir = Integer.parseInt(st.nextToken());
    				solve(n-1, dir);
    			}
    			
    			
    			for(int i=0;i<4;i++) {
    				if(map[i][0]==1) { // s 극 일때 
    					ans+=Math.pow(2, i);
    //					System.out.println(i);
    				}
    			}
    			
    			System.out.println("#" + tc + " " + ans);
    			
    		}
    		
    	}
    	
    	static void solve(int x, int d) {
    		dArr[x] = d; // 받아온 방향 
    		
    		// 오른쪽으로 회전
    		for(int i=x+1;i<4;i++) {
    			if(map[i][6]==map[i-1][2]) {
    				break;
    			}
    			else dArr[i] = -dArr[i-1];
    		}
    		
    		// 왼쪽으로 회전 
    		for(int i=x-1;i>=0;i--) {
    			if(map[i][2]==map[i+1][6]) {
    				break;
    			}
    			else dArr[i] = -dArr[i+1];
    		}
    		
    		rotation();
    	}
    	
    	// 0 1 2 3 4 5 6 7
    	// 0 0 1 0 0 1 0 0
    	
    	// 회전 
    	static void rotation() {
    		for(int i=0;i<4;i++) {
    			if(dArr[i]==0) continue;
    			else if(dArr[i]==1) {
    				// 시계 방향 회전
    				int tmp = map[i][7];
    				
    				for(int y=7;y>=1;y--) {
    					map[i][y] = map[i][y-1];
    				}
    				
    				map[i][0]=tmp;
    			}else if(dArr[i]==-1){ // -1 
    				// 반시계 방향 회전
    				int tmp = map[i][0];
    				
    				for(int y=0;y<=6;y++) {
    					map[i][y] = map[i][y+1];
    				}
    				
    				map[i][7]=tmp;
    			}
    		}
    	}
    
    }

     

    참고로 백준 문제는 "톱니바퀴"랑 동일한 문제였고! 입출력 형식만 아래처럼 다르게 하면 바로 정답이 나온다!

    https://www.acmicpc.net/problem/14891

    음음 무려 4일전이었군...제출이..

    이걸 왜 이제 쓰고있는지 

     

    개미한테 부지런함을 배우자! 

    아차차 백준 전체 코드는 아래랑 같다!

    import java.io.*;
    import java.util.*;
    
    class Main {
    
        static int k, map[][], ans, n, dir, arr[];
    
        public static void main(String[] args) throws Exception {
    
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            StringTokenizer st;
    
            map = new int[5][9];
    
            // 4개의 자석
            for(int i=1;i<=4;i++) {
                String line = br.readLine();
                // 각 자석은 8개의 '날' 을 가지고 있음
                for(int j=0;j<8;j++) {
                    map[i][j] = line.charAt(j) -'0';
                }
            }
    
            st = new StringTokenizer(br.readLine());
            k = Integer.parseInt(st.nextToken());
    
            // k 번 회전
            for(int i=0;i<k;i++) {
                arr = new int[5];
                st = new StringTokenizer(br.readLine());
                n = Integer.parseInt(st.nextToken()); // 몇 번
                dir = Integer.parseInt(st.nextToken()); // 방향
                solve(n , dir); // 회전 할 때마다
                // map 은 공통 으로 활용
            }
    
            ans = 0;
            // 1 번 -> N극 0점 S극 1점 (2 의 0승)
            // 2 번 -> N극 0점 S극 2점 (2 의 1승)
            // 3 번 -> N극 0점 S극 4점 (2 의 2승)
            // 4 번 -> N극 0점 S극 8점 (2 의 3승)
            for(int i=1;i<=4;i++) {
                if(map[i][0]==1) { // S극 일 때만 점수
                    ans+=Math.pow(2, i-1);
                }
            }
    
            // 임의의 자석 1 칸씩 k 번 회전
            // 하나의 자석이 1칸 회전 될 때,
            System.out.println(ans);
    
        }
    
        // 처음 : 화살표 위치
        // S극 : 1
        // N극 : 0
        // 시계 : 1, 반시계 : -1
        static void solve(int x, int d){
            arr[x] = d; // 방향 배열
    
            // idx : 3이랑 7 이랑 물려 있음
            // 1. idx 에 물려 있는 값 먼저 확인
            // x 랑 x+1
            // 2. 값이 다르면 서로 다른 극
            // 3. 서로 반대 방향 으로 회전
    
            // 오른쪽
            for(int i=x+1;i<=4;i++) {
                if(map[i][6]==map[i-1][2]) {
                    break;
                }
                else arr[i] = -arr[i-1];
            }
    
            // 왼쪽
            for(int i=x-1;i>=1;i--) {
                if(map[i+1][6]==map[i][2]) {
                    break;
                }
                else arr[i] = -arr[i+1];
            }
    
            rotation();
    
        }
    
        // map 회전
        static void rotation() {
            // x : 행 번호
            for(int i=1;i<=4;i++) {
                if(arr[i]==0) continue;
                else if(arr[i]==1) {
                    // 시계
                    // 1. 마지막 값을 tmp 에 저장
                    int tmp = map[i][7];
                    // 2. 한 칸 식 오른쪽
                    for(int y=7;y>=1;y--) {
                        map[i][y] = map[i][y-1];
                    }
                    // 3. tmp 에 저장한 값 처음에 다시 저장
                    map[i][0] = tmp;
                }else if(arr[i]==-1) {
                    // 반시계
                    // 1. 처음 값을 tmp 에 저장
                    int tmp = map[i][0];
                    // 2. 한 칸 씩 왼쪽
                    for(int y=0;y<=6;y++) {
                        map[i][y] = map[i][y+1];
                    }
                    // 3. tmp 에 저장한 값  마지막에 다시 저장
                    map[i][7] = tmp;
                }
            }
        }
    }

    'Java' 카테고리의 다른 글

    [Java] 프로그래머스 - 모의고사  (1) 2024.10.23
    [Java] 프로그래머스 - 최소 직사각형  (0) 2024.10.23
    [Java] 메모리 구조  (1) 2024.01.27
    [JAVA] 숫자와 문자  (0) 2024.01.02
    [JAVA] 언어소개 & 프로그램 동작  (2) 2024.01.02
Designed by Tistory.