반응형

 

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		
		
		Scanner sc = new Scanner(System.in);
		
		int tc = sc.nextInt();
		
		for(int i=0;i<tc;i++){
			
			int n = sc.nextInt();
			int cnt =0;
			int[] dp = new int[n+1];
			
			
			for(int j=2;j<=n;j++){
				for(int k=1;k<=n;k++){
					if(j*k > n)continue;
					if(dp[j*k]==0){
						dp[j*k]=1;
					}else if(dp[j*k]==1){
						dp[j*k]=0;
					}
				}
			}
			
			for(int j=1;j<=n;j++){
				if(dp[j] == 0){
					cnt++;
				}
			}
			System.out.println(cnt);
		}
	}
}
반응형
반응형

빙산이 2개 이상의 덩어리로 분리될때의 년도 Count를 구하는 문제이다.

풀이 접근 방법은 먼저

(1) dfs로(bfs로도 적용할 수 있다) 덩어리 Count를 구하는 부분과,

(2) 1년이란 시간이 흘렀을때 빙산의 변화된 모습을 Map[n][m] 에 어떻게 처리할지를 고민했다.

위 두 가지 케이스 처리를 위해 (1), (2) 번을 2덩어리로 분리될때까지 while문으로 감싸서 처리했다.

일단 2덩어리로 분리되는 dfs 풀이는 정말 기본 적인 dfs 재귀함수를 통해 재귀함수가 종료될때

덩어리 Count+1 을 해주었다.

//divCnt : 빙산 덩어리 Count

for(int i=0;i<n;i++) {
    for(int j=0;j<m;j++) {
        if(map[i][j] > 0 && visit[i][j] == 0) {
            flag = true;
            GetDFS(i, j);
            divCnt++;
        }
    }
}

// 분리된 빙산 체크
public static void GetDFS(int x, int y){
    visit[x][y] = 1;

    int[] xx = {-1, 0, 1, 0};
    int[] yy = {0, 1, 0 ,-1};

    for(int i=0;i<4;i++) {
        int ax = x + xx[i];
        int ay = y + yy[i];

        if(ax >= 0 && ay >= 0 && ax<n && ay<m && map[ax][ay] > 0 && visit[ax][ay] == 0 ) {
            GetDFS(ax, ay);
        }
    }
}

빙산의 1년 후 모습은 동,서,남,북 방면의 ‘0’ 개수만큼 melt[n][m] 배열에 +1씩 해주고

실제 빙산 지도에서 melt[n][m] 를 빼주는 방식으로 처리하였다.

// 녹는거 처리
for(int i=0;i<n;i++) {
    for(int j=0;j<m;j++) {
        if(map[i][j] > 0) {
            for(int k=0;k<4;k++) {
                int ax = i + xx[k];
                int ay = j + yy[k];

                if(ax>=0 && ay>=0 && ax<n && ay<m && map[ax][ay] == 0) {
                    melt[i][j]++;
                }
            }
        }
    }
}

for(int i=0;i<n;i++) {
    for(int j=0;j<m;j++) {
        if(melt[i][j] > 0) {                        
            map[i][j] = map[i][j] - melt[i][j] < 0 ? 0 : map[i][j] - melt[i][j];
        }
    }
}

이제

(1) dfs로(bfs로도 적용할 수 있다) 덩어리 Count를 구하기

(2) 1년이란 시간이 흘렀을때 빙산의 변화된 모습을 Map[n][m] 처리

(1), (2) 번을 모두 처리하였으며, 문제에서 주어진

‘만일 전부 다 녹을 때까지 두 덩어리 이상으로 분리되지 않으면 프로그램은 0을 출력한다.’

처리는 flag 변수를 통해 처리했다.

[풀이]

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

public class BOJ2573 {

    static int n;
    static int m;
    static int[][] map;
    static int[][] visit;
    static int[][] melt; 
    static int year = 0;


    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());

        map = new int[n][m];

        int[] xx = {-1, 0, 1, 0};
        int[] yy = {0, 1, 0, -1};

        // 빙산 입력받기
        for(int i=0; i<n; i++) {
            st = new StringTokenizer(br.readLine(), " ");
            for(int j=0; j<m; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        boolean flag = true;

        while(true) {
            visit = new int[n][m];
            melt = new int[n][m];
            int divCnt = 0;

            // 분리 체크
            flag = false;

            for(int i=0;i<n;i++) {
                for(int j=0;j<m;j++) {
                    if(map[i][j] > 0 && visit[i][j] == 0) {
                        flag = true;
                        GetDFS(i, j);
                        divCnt++;
                    }
                }
            }

            if(divCnt > 1) {
                System.out.println(year);
                return;
            }

            if(!flag) {
                System.out.println(0);
                return;
            };

            // 녹는거 처리
            for(int i=0;i<n;i++) {
                for(int j=0;j<m;j++) {
                    if(map[i][j] > 0) {
                        for(int k=0;k<4;k++) {
                            int ax = i + xx[k];
                            int ay = j + yy[k];

                            if(ax>=0 && ay>=0 && ax<n && ay<m && map[ax][ay] == 0) {
                                melt[i][j]++;
                            }
                        }
                    }
                }
            }

            for(int i=0;i<n;i++) {
                for(int j=0;j<m;j++) {
                    if(melt[i][j] > 0) {                        
                        map[i][j] = map[i][j] - melt[i][j] < 0 ? 0 : map[i][j] - melt[i][j];
                    }
                }
            }

            year++;

        }
    }

    // 분리된 빙산 체크
    public static void GetDFS(int x, int y){
        visit[x][y] = 1;

        int[] xx = {-1, 0, 1, 0};
        int[] yy = {0, 1, 0 ,-1};

        for(int i=0;i<4;i++) {
            int ax = x + xx[i];
            int ay = y + yy[i];

            if(ax >= 0 && ay >= 0 && ax<n && ay<m && map[ax][ay] > 0 && visit[ax][ay] == 0 ) {
                GetDFS(ax, ay);
            }
        }
    }
}
반응형
반응형

움직임이 좌,우,상,하 가 아닌 나이트의 이동을 가진 살짝 이동경로만 변형된 기본적인 BFS 문제입니다.

체스 나이트의 움직임은 위 그림과 같이 움직일 수 있습니다.

기존 좌,우,상,하 움직이는 BFS 문제는

int[4] x = {-1,0,1,0} // x축 기준: 좌, 상, 우, 하
int[4] y = {0,1,0,-1} // y축 기준: 좌, 상, 우, 하
 

처럼 움직인 반면 나이트의 움직임은 배열로 아래 그림 번호 순대로 선언 할 수 있습니다.

int[8] x = {-1, 1, 2, 2, 1, -1, -2, -2}
int[8] y = {2, 2, 1, -1, -2, -2, -1, 1}

이제 나이트의 이동 순서를 알고 있으므로, 기본 BFS 문제와 동일하게

Queue 를 선언하여 현재 위치, 그리고 이동한 위치까지의 움직인 횟 수를 저장하고 반복문을 통해

도착지에 도달하면 도착지까지의 움직임 횟 수를 출력해주면 됩니다.

 

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

class Location7562 {
	int x;
	int y;
	int cnt;
	
	public Location7562(int x, int y, int cnt) {
		// TODO Auto-generated constructor stub
		this.x = x;
		this.y = y;
		this.cnt = cnt;
	}
}

public class BOJ7562 {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Scanner sc = new Scanner(System.in);
		
		int tc = sc.nextInt();
		int[] result = new int[tc];
		int[] xx = {-1, 1, 2, 2, 1, -1, -2, -2};
		int[] yy = {2, 2, 1, -1, -2, -2, -1, 1};
		
		for(int i=0 ;i<tc;i++) {
			int l = sc.nextInt();
			int n = sc.nextInt();
			int m = sc.nextInt();
			int destinationX = sc.nextInt();
			int destinationY = sc.nextInt();
			
			int[][] map = new int[l][l];
			int[][] visit = new int[l][l];
			Queue<Location7562> q = new LinkedList<>();
			
			q.offer(new Location7562(n, m, 0));
			visit[n][m] = 1;
			
			while(!q.isEmpty()) {
				int x = q.peek().x;
				int y = q.peek().y;
				int cnt = q.poll().cnt;
				
				for(int j=0;j<8;j++) {
					int ax = x + xx[j];
					int ay = y + yy[j];
										
					if(ax >= 0 && ay>= 0 && ax< l && ay< l && visit[ax][ay] == 0) {
						if(ax == destinationX && ay == destinationY) {
							result[i] = cnt+1;
							q.clear();
							break;
						}
						
						visit[ax][ay] = 1;
						q.offer(new Location7562(ax, ay, cnt+1));
					}
				}
			}
		}
		
		for(int i=0;i<result.length;i++) {
			System.out.println(result[i]);
		}
	}

}
반응형

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

[Baekjoon] #6359 만취한 상범  (0) 2024.03.08
[Baekjoon] #2573 빙산  (0) 2022.07.14
[Baekjoon] #2869 달팽이는 올라가고 싶다  (0) 2022.07.04
[Baekjoon] #10872 팩토리얼  (0) 2022.07.03
[Baekjoon] #1520 내리막 길  (0) 2022.06.29
반응형

while문을 통해 처음 문제를 접근하였지만, 기본 수학 문제로 반복문이 아닌 식을 통해 문제를 풀도록 유도 하는 문제이다.

while문 등 아래와 같이 반복문을 통해 풀게 될 경우 문제의 조건인 (1 ≤ B < A ≤ V ≤ 1,000,000,000)

10억이란 숫자로 반복문을 처리하게 되어 시간 초과가 발생한다.


        int cur = 0;
        int days = 1;

        while(true) {
            cur = cur + a;

            if(cur >= v) {
                System.out.println(days);
                return;
            }

            cur = cur -b;
            days++;
        }

즉, 수학적 접근으로 아래와 같은 식을 만들 수 있다.

V(나무 막대 높이) / A(오르는 높이) - B (내려가는 높이)

하지만, 위와 같은 식을 처리할 경우 ‘또, 정상에 올라간 후에는 미끄러지지 않는다.’

를 고려해서 식을 바꿔주어야한다.

여기서 접근한 방식은, 높이에서 - 내려가는 높이를 뺀 후, 하루를 올라야하는지 아니면 정상에 도달했는지를 구하는 방식으로 처리하였다.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class BaekjoonAlgo_2869 {

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub

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

        int a = Integer.parseInt(st.nextToken());
        int b = Integer.parseInt(st.nextToken());
        int v = Integer.parseInt(st.nextToken());


        int days = (v-b) / (a - b);

        if(((v-b) % (a - b)) != 0) {
            days++;
        }

        System.out.println(days);
    }
}
  • 추가적으로 Java11에서는 Scanner로 처리 시 시간초과가 발생하여 BufferedReader로 변경하여 제출하였다.
반응형

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

[Baekjoon] #2573 빙산  (0) 2022.07.14
[Baekjoon] #7562 나이트의 이동  (0) 2022.07.06
[Baekjoon] #10872 팩토리얼  (0) 2022.07.03
[Baekjoon] #1520 내리막 길  (0) 2022.06.29
[Baekjoon] #11651 좌표 정렬하기2  (0) 2022.06.28
반응형

import java.util.Scanner;

public class Main {

	static int result = 1;
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		
		refact(n);
		
		System.out.println(result);
	}
	
	public static void refact(int x) {
		if(x > 0) {
			result *=x;
			refact(x-1);
		}
	}

}
반응형

+ Recent posts