Java

[JAVA] 4013번 : 특이한 자석 (SWEA) & 14891번 : 톱니바퀴 (BOJ)

Eunice99 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;
            }
        }
    }
}