[문제링크]

 

4056번: 스-스-스도쿠

바다에서 수학을 좋아하기로 유명한 오징어의 취미는 스도쿠이다. 스도쿠는 9*9칸으로 이루어져 있으며, 3*3칸에 1~9까지가 1번씩, 각각의 가로줄에도 1번씩, 세로줄에도 1번씩 들어가게 만드는 게

www.acmicpc.net

 

0. 기존 스도쿠 코드의 활용(링크)

 

1. 기존 코드부터 true/false 리턴값으로 성공/실패를 알 수 있으니 함수 내부는 추가적 처리 불필요

 

2. 초기 입력값부터 규칙에 위배될 수 있으니, 시작하기 전 체크한다

 

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main{
	
	static int[][] map;
	static boolean[][]rowChk;
	static boolean[][]colChk;
	
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();

		int tc = pint(br.readLine());
		for (int testcase = 1; testcase <= tc; testcase++) {
			int N = 9;
			map = new int[N][N];
			boolean success=true;
			rowChk = new boolean[N][N+1];
			colChk = new boolean[N][N+1];
			for (int i = 0; i < N; i++) {
				String s = br.readLine();
				for (int j = 0; j < N; j++) {
					map[i][j]=s.charAt(j)-'0';
					if(map[i][j]!=0) {
						if(!rowChk[i][map[i][j]])rowChk[i][map[i][j]]=true;
						else success=false;//row체크
						if(!colChk[j][map[i][j]])colChk[j][map[i][j]]=true;
						else success=false;//col체크
					}
				}
			}

			//block 체크
			for (int bx = 0; bx < 9; bx+=3) {
				for (int by = 0; by < 9; by+=3) {
					boolean[]blockChk=new boolean[N+1];
					for (int i = 0; i < 3; i++) {
						for (int j = 0; j < 3; j++) {
							if(map[bx+i][by+j]==0)continue; // 0일때는 넘어간다
							if(!blockChk[ map[bx+i][by+j] ])
								blockChk[ map[bx+i][by+j] ]=true;//0이 아닌 값을 처음 만나면 true
							else {
								success=false;//0이 아닌 값을 다시 만나면 실패한 스도쿠
							}
						}
					}
				}
			}
			
			//초기 입력값이 valid하다면
			if(success)success = rec(0);
			
			if(success) {
				for (int i = 0; i < N; i++) {
					for (int j = 0; j < N; j++) {
						sb.append(map[i][j]);
					}sb.append('\n');
				}
			}
			else {
				sb.append("Could not complete this grid.\n");
			}sb.append('\n');
		}System.out.println(sb);
		
		
	}
	static boolean rec(int cur) {
		if(cur==81)return true;
		int x = cur/9;
		int y = cur%9;
		if(map[x][y]==0) {
			for (int i = 1; i <= 9; i++) {
				if(chk(x,y,(x/3)*3, (y/3)*3, i)) {
					rowChk[x][i]=true;
					colChk[y][i]=true;
					map[x][y]=i;
					
					if(rec(cur+1))return true;
					
					rowChk[x][i]=false;
					colChk[y][i]=false;
				}
			}
			map[x][y]=0;
		}
		else {
			//이미 뭔가 수가 있다
			return rec(cur+1);
		}
		return false;
	}
	
	static boolean chk(int row, int col, int x, int y, int val) {
		boolean ret=true;
		if(rowChk[row][val] || colChk[col][val])ret=false;
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				if(map[x+i][y+j]==val)ret=false;
		return ret;
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

'알고리즘 문제 풀이 > BOJ 골드' 카테고리의 다른 글

[백준] 1967 - 트리의 지름  (0) 2021.04.18
[백준] 2263 - 트리의 순회  (0) 2021.04.16
[백준] 17471 - 게리맨더링  (0) 2021.04.16
[백준] 2239 - 스도쿠  (0) 2021.04.16
[백준] 2096 - 내려가기  (0) 2021.04.16
[백준] 15961 - 회전 초밥  (0) 2021.04.15
[백준] 2638 - 치즈  (0) 2021.04.15

[문제링크]

 

2239번: 스도쿠

스도쿠는 매우 간단한 숫자 퍼즐이다. 9×9 크기의 보드가 있을 때, 각 행과 각 열, 그리고 9개의 3×3 크기의 보드에 1부터 9까지의 숫자가 중복 없이 나타나도록 보드를 채우면 된다. 예를 들어 다

www.acmicpc.net

 

0. x, y좌표에 val값이 들어갈 수 있으려면

  - 같은 행에 val이 존재해선 안되고

  - 같은 열에 val이 존재해선 안되고

  - 같은 3*3블록에 val이 존재해선 안된다

  - chk함수로 이를 판단

  - 하나의 행/열에서 1~9의 숫자는 한번씩만 등장하므로, boolean배열로 중복 여부를 판단한다

 

1. x,y의 값이 0일때, 1~9까지 가능한 모든 숫자를 넣어보면서 다음 단계로 진행한다

  - 0이 아니면 바로 다음으로 진행

 

2. 진행이 불가능하면 false반환, 다음 숫자를 시도

 

3. 모든 칸에 합당한 숫자가 채워져 cur값이 81까지 진행됬다면, 스도쿠가 완성된 것으로 true를 반환한다

 

4. 해답이 여러개 존재한다 해도, 1부터 9까지, 작은수를 우선해서 수행했으므로

  - 첫번째 해답은 항상 가장 작은 해답이다

 

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main{
	
	static int[][] map;
	static boolean[][]rowChk;
	static boolean[][]colChk;
	
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		
		int N = 9;
		map = new int[N][N];
		rowChk = new boolean[N][N+1];
		colChk = new boolean[N][N+1];
		for (int i = 0; i < N; i++) {
			String s = br.readLine();
			for (int j = 0; j < N; j++) {
				map[i][j]=s.charAt(j)-'0';
				if(map[i][j]!=0) {
					rowChk[i][map[i][j]]=true;
					colChk[j][map[i][j]]=true;
				}
			}
		}
		
		rec(0);
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				sb.append(map[i][j]);
			}sb.append('\n');
		}System.out.println(sb);
		
	}
	static boolean rec(int cur) {
		if(cur==81)return true;
		int x = cur/9;
		int y = cur%9;
		if(map[x][y]==0) {
			for (int i = 1; i <= 9; i++) {
				if(chk(x,y,(x/3)*3, (y/3)*3, i)) {
					rowChk[x][i]=true;
					colChk[y][i]=true;
					map[x][y]=i;
					
					if(rec(cur+1))return true;
					
					rowChk[x][i]=false;
					colChk[y][i]=false;
				}
			}
			map[x][y]=0;
		}
		else {
			//이미 수가 있다
			return rec(cur+1);
		}
		return false;
	}
	
	static boolean chk(int row, int col, int x, int y, int val) {
		boolean ret=true;
		if(rowChk[row][val] || colChk[col][val])ret=false;
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				if(map[x+i][y+j]==val)ret=false;
		return ret;
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

'알고리즘 문제 풀이 > BOJ 골드' 카테고리의 다른 글

[백준] 2263 - 트리의 순회  (0) 2021.04.16
[백준] 17471 - 게리맨더링  (0) 2021.04.16
[백준] 4056 - 스-스-스도쿠  (0) 2021.04.16
[백준] 2096 - 내려가기  (0) 2021.04.16
[백준] 15961 - 회전 초밥  (0) 2021.04.15
[백준] 2638 - 치즈  (0) 2021.04.15
[백준] 15686 - 치킨 배달  (0) 2021.04.15

[문제링크]

 

2096번: 내려가기

첫째 줄에 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 N개의 줄에는 숫자가 세 개씩 주어진다. 숫자는 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 중의 하나가 된다.

www.acmicpc.net

 

0. 직전 단계의 결과 중 최소 / 최대값만을 취하는 간단한 DP

 

1. 메모리 제한이 작으므로 직전 단계만을 저장하도록 2칸의 배열을 잡는다

 

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

public class Main{
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		
		int N = pint(br.readLine());
		int[][]max = new int[2][3];
		int[][]min = new int[2][3];
		
		for (int i = 0; i < N; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine(), " ");
			int n1 = pint(st.nextToken());
			int n2 = pint(st.nextToken());
			int n3 = pint(st.nextToken());
			
			max[1][0]=n1 + Math.max(max[0][0], max[0][1]);
			min[1][0]=n1 + Math.min(min[0][0], min[0][1]);
			
			max[1][1]=n2 + Math.max(max[0][0], Math.max(max[0][1], max[0][2]));
			min[1][1]=n2 + Math.min(min[0][0], Math.min(min[0][1], min[0][2]));
			
			max[1][2]=n3 + Math.max(max[0][1], max[0][2]);
			min[1][2]=n3 + Math.min(min[0][1], min[0][2]);
			
			for (int j = 0; j < 3; j++) {
				max[0][j]=max[1][j];
				min[0][j]=min[1][j];
			}
		}
		System.out.println(Math.max(max[1][0], Math.max(max[1][1], max[1][2]))+" "+
				Math.min(min[1][0], Math.min(min[1][1], min[1][2])));
		
	}
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

'알고리즘 문제 풀이 > BOJ 골드' 카테고리의 다른 글

[백준] 17471 - 게리맨더링  (0) 2021.04.16
[백준] 4056 - 스-스-스도쿠  (0) 2021.04.16
[백준] 2239 - 스도쿠  (0) 2021.04.16
[백준] 15961 - 회전 초밥  (0) 2021.04.15
[백준] 2638 - 치즈  (0) 2021.04.15
[백준] 15686 - 치킨 배달  (0) 2021.04.15
[백준] 9935 - 문자열 폭발  (0) 2021.04.14

[문제링크]

 

SW Expert Academy

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

swexpertacademy.com

 

0. 현재 파이프의 모양 - 인접 파이프의 모양 에 따라 갈수 있는지 없는지 여부가 결정된다

  - 총 4방향이므로, 4개의 bit에 bitmask로 저장해 정보를 나타낸다.

 

1. 입력값(0~7)에 따라 해당하는 bitmask정보를 부여한다

 

2. 시작점에서 time만큼 bfs를 돌며

  - 현재 노드에서 상/하/좌/우 통로가 존재하고 + 진행 노드에서 하/상/우/좌 통로가 존재한다면

  - 진행 가능, 큐에 넣는다

  - 방문체크 대신 큐에 넣을때 자기 위치의 값을 0으로 바꿔 재방문을 방지한다

 

3. time이 다 지났다면 (혹은 도중에 탐색을 마쳐 qu가 비었다면)

  - 방문할때마다 1씩 증가시켜준 cnt를 출력, 종료한다

 

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

public class Solution{
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		
		int tc = pint(br.readLine());
		for (int testcase = 1; testcase <= tc; testcase++) {
			StringTokenizer st = new StringTokenizer(br.readLine(), " ");
			int n = pint(st.nextToken());
			int m = pint(st.nextToken());
			int x = pint(st.nextToken())+1;
			int y = pint(st.nextToken())+1;
			int t = pint(st.nextToken());
			
			int[][] map = new int[n+2][m+2];
			
			for (int i = 1; i < n+1; i++) {
				st=new StringTokenizer(br.readLine()," ");
				for (int j = 1; j < m+1; j++) {
					int temp = pint(st.nextToken());
					if(temp==1)map[i][j]=0b1111;
					else if(temp==2)map[i][j]=0b1100;
					else if(temp==3)map[i][j]=0b0011;
					else if(temp==4)map[i][j]=0b1001;
					else if(temp==5)map[i][j]=0b0101;
					else if(temp==6)map[i][j]=0b0110;
					else if(temp==7)map[i][j]=0b1010;
				}
			}
			
			Queue<int[]> qu = new LinkedList<int[]>();
			qu.add(new int[] {x,y});
			int cnt=0;
			int time=0;
			while(time++<t && !qu.isEmpty()) {
				int len = qu.size();
				
				for (int i = 0; i < len; i++) {
					int[] cur=qu.poll();
					int temp = map[cur[0]][cur[1]];
					if(temp==0)continue;
					
					if((temp&1<<3)!=0 && (map[cur[0]-1][cur[1]]&1<<2)!=0)
						qu.offer(new int[] {cur[0]-1,cur[1]});
					if((temp&1<<2)!=0 && (map[cur[0]+1][cur[1]]&1<<3)!=0)
						qu.offer(new int[] {cur[0]+1,cur[1]});
					if((temp&1<<1)!=0 && (map[cur[0]][cur[1]-1]&1<<0)!=0)
						qu.offer(new int[] {cur[0],cur[1]-1});
					if((temp&1<<0)!=0 && (map[cur[0]][cur[1]+1]&1<<1)!=0)
						qu.offer(new int[] {cur[0],cur[1]+1});
					
					cnt++;
					map[cur[0]][cur[1]]=0;
				}
			}
			sb.append("#").append(testcase).append(" ").append(cnt).append("\n");
		}//end of tc
		System.out.println(sb);
	}

	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

'알고리즘 문제 풀이 > SWEA' 카테고리의 다른 글

[SWEA] 2115 - 벌꿀채취  (0) 2021.04.22
[SWEA] 8382 - 방향전환  (0) 2021.04.19
[SWEA] 8458 - 원점으로 집합  (0) 2021.04.19
[SWEA] 5656 - 벽돌깨기  (0) 2021.04.15
[SWEA] 4014 - 활주로 건설 / [백준] 14890 - 경사로  (0) 2021.04.13
[SWEA] 1249 - 보급로  (0) 2021.04.12
[SWEA] 5644 - 무선충전  (0) 2021.04.12

[문제링크]

 

15961번: 회전 초밥

첫 번째 줄에는 회전 초밥 벨트에 놓인 접시의 수 N, 초밥의 가짓수 d, 연속해서 먹는 접시의 수 k, 쿠폰 번호 c가 각각 하나의 빈 칸을 사이에 두고 주어진다. 단, 2 ≤ N ≤ 3,000,000, 2 ≤ d ≤ 3,000, 2

www.acmicpc.net

 

0. 슬라이딩 윈도우로, 다음 초밥을 넣고, 첫 초밥은 빼가며 종류를 센다 (큐 사용)

  - 회전초밥벨트이므로, 시작한 K개의 초밥이 마지막 초밥에 이어진다 

  - [시작부분] - [나머지] - [시작부분] 의 순서로 저장해서 처리

 

1. end포인터를 1씩 늘려가며 k개의 초밥을 받고, 종류를 센다

 

2. end포인터가 N+k가 될 때까지, end포인터의 초밥을 포함시키고, fst포인터의 초밥을 내보내는것을 반복한다

 

3. 위 과정중 구해진 가장 큰 cnt를 출력

 

개선점 : 모든 입력을 받고 시작하게 되면, 초밥을 큐로 관리할 필요가 없다

  - 큐 대신 포인터변수 2개만 사용해도 된다.

  - 반영함

 

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

public class Main{
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int N = Integer.parseInt(st.nextToken());
		int d = Integer.parseInt(st.nextToken());
		int k = Integer.parseInt(st.nextToken());
		
		//d+1개의 배열 생성.
		int[] count = new int[d+1];
		count[Integer.parseInt(st.nextToken())]=1;//쿠폰은 항상 먹는다
		
		//초밥 종류 cnt변수
		int cnt=1, max=0;
		
		//처음 K개 저장할 배열 생성
		int[] saveFst = new int[N+k];
		for (int i = 0; i < N; i++) {
			saveFst[i]=Integer.parseInt(br.readLine());;
			if(i<k)saveFst[N+i]=saveFst[i];
		}
		
		int fst=0, end=0;
		for (; end < k; end++) {
			if(++count[saveFst[end]]==1)cnt++;
		}
		max=cnt;
		for (; end < N+k; end++) {
			if(++count[saveFst[end]]==1)cnt++;
			
			if(--count[saveFst[fst++]]==0)cnt--;
			
			if(max<cnt)max=cnt;
		}
		System.out.println(max);
		
	}
}

결과 화면

'알고리즘 문제 풀이 > BOJ 골드' 카테고리의 다른 글

[백준] 4056 - 스-스-스도쿠  (0) 2021.04.16
[백준] 2239 - 스도쿠  (0) 2021.04.16
[백준] 2096 - 내려가기  (0) 2021.04.16
[백준] 2638 - 치즈  (0) 2021.04.15
[백준] 15686 - 치킨 배달  (0) 2021.04.15
[백준] 9935 - 문자열 폭발  (0) 2021.04.14
[백준] 1019 - 책 페이지  (0) 2021.04.13

[문제링크]

 

2638번: 치즈

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5≤N, M≤100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로 표

www.acmicpc.net

 

0. 내부 공기엔 인접해도 녹지 않으므로, 외곽 공기에 대해서만 bfs를 진행.

  - 0,0은 항상 밖의 공기이다

 

1. 0,0을 시작점으로, 외곽 공기를 bfs로 순회한다

  - 치즈를 처음 만나면, 표시만 한다

  - 치즈를 2번째로 만나면, 제거 대상 치즈로 판단, 저장한다

 

2. 1번에서 저장된 제거대상 치즈를 제거한다

 

3. 위 과정을 치즈가 없어질때까지 반복한다

 

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

public class Main{
	static int[] dx= {1,0,-1,0};
	static int[] dy= {0,1,0,-1};
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int n = pint(st.nextToken());
		int m = pint(st.nextToken());
		int[][]map = new int[n][m];
		int chCnt=0;
		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine()," ");
			for (int j = 0; j < m; j++) {
				map[i][j]=pint(st.nextToken());
				if(map[i][j]==1)chCnt++;
			}
		}
		int time=0;
		
		Queue<int[]>qu = new LinkedList<int[]>();
		Queue<int[]>removeCh = new LinkedList<int[]>();
		
		while(chCnt!=0) {
			time++;
			//bfs돌며 제거할 치즈 탐색
			int[][]isV = new int[n][m];
			qu.offer(new int[] {0,0});
			isV[0][0]=1;
			while(!qu.isEmpty()) {
				int[] ch = qu.poll();
				
				for (int i = 0; i < 4; i++) {
					int tx = ch[0]+dx[i], ty=ch[1]+dy[i];
					if(tx<0||tx>=n||ty<0||ty>=m)continue;
					
					//미방문 공기
					if(isV[tx][ty]==0 && map[tx][ty]==0) {
						isV[tx][ty]=1;
						qu.offer(new int[] {tx,ty});
					}
					//치즈 처음 만남
					else if(isV[tx][ty]==0) {
						isV[tx][ty]=1;
					}
					//치즈 2번째 만남
					else if(isV[tx][ty]==1 && map[tx][ty]==1) {
						isV[tx][ty]=2;
						removeCh.offer(new int[] {tx,ty});
					}
					
				}
			}
			
			//녹을 치즈 제거
			chCnt-=removeCh.size();
			while(!removeCh.isEmpty()) {
				int[] ch = removeCh.poll();
				map[ch[0]][ch[1]]=0;
			}
			
		}
		
		System.out.println(time);
	}
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

'알고리즘 문제 풀이 > BOJ 골드' 카테고리의 다른 글

[백준] 2239 - 스도쿠  (0) 2021.04.16
[백준] 2096 - 내려가기  (0) 2021.04.16
[백준] 15961 - 회전 초밥  (0) 2021.04.15
[백준] 15686 - 치킨 배달  (0) 2021.04.15
[백준] 9935 - 문자열 폭발  (0) 2021.04.14
[백준] 1019 - 책 페이지  (0) 2021.04.13
[백준] 1566 - P배열  (0) 2021.04.13

[문제링크]

 

15686번: 치킨 배달

크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸

www.acmicpc.net

 

0. 치킨집의 총 개수를 모르므로 arraylist로 관리

  - 살릴 치킨집의 개수는 알고 있으므로 배열로 관리

 

1. 가능한 모든 살릴수 있는 치킨집의 조합을 구한다 (combi 함수)

 

2. 각 조합에 대해, 치킨집 위치를 시작으로 bfs를 돌려 모든 집까지의 최소 거리를 구한다 (bfs함수)

 

3. bfs함수에서 구한 최소 거리가 더 작다면 min을 갱신

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main{

	static boolean[][]isV;//방문체크
	static int[][]map;
	static int[][]select;//살릴 치킨집
	static List<int[]>chicken;//모든 치킨집
	static int ans,n,m;
	static Queue<int[]> qu;
    
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		n = pint(st.nextToken());
		m = pint(st.nextToken());
		
		map = new int[n+2][n+2];
		chicken = new ArrayList<>();
		//-1 패딩
		for (int i = 0; i < n+2; i++) {
			map[i][0]=-1;map[i][n+1]=-1;
			map[0][i]=-1;map[n+1][i]=-1;
		}
		
		//입력받기 + 치킨집 저장
		for (int i = 1; i <= n; i++) {
			st=new StringTokenizer(br.readLine());
			for (int j = 1; j <= n; j++) {
				map[i][j]=pint(st.nextToken());
				if(map[i][j]==2)chicken.add(new int[] {i,j});
			}
		}
		
		ans=Integer.MAX_VALUE;
		select=new int[m][2];
		combi(0, 0);
		System.out.println(ans);
        
	}
    
	static void combi(int cnt, int prev) {
		if(cnt==m) {
			qu = new LinkedList<int[]>();
			for (int i = 0; i < m; i++) {
				qu.offer(new int[] {select[i][0], select[i][1], 0});
			}
			ans = Math.min(ans, bfs());
			return;
		}
		
		for (int i = prev, len = chicken.size(); i < len; i++) {
			select[cnt][0]=chicken.get(i)[0];
			select[cnt][1]=chicken.get(i)[1];
			combi(cnt+1, i+1);
		}
	}
	
	static int bfs() {
		isV = new boolean[n+2][n+2];
		int dist=0;
		while(!qu.isEmpty()) {
			int[] cur = qu.poll();
			
			if(map[cur[0]][cur[1]]==1) {
				dist+=cur[2];
			}
			
			if(!isV[cur[0]+1][cur[1]] && map[cur[0]+1][cur[1]]>=0) {
				isV[cur[0]+1][cur[1]]=true;
				qu.offer(new int[] {cur[0]+1, cur[1], cur[2]+1});
			}
			if(!isV[cur[0]-1][cur[1]] && map[cur[0]-1][cur[1]]>=0) {
				isV[cur[0]-1][cur[1]]=true;
				qu.offer(new int[] {cur[0]-1, cur[1], cur[2]+1});
			}
			if(!isV[cur[0]][cur[1]+1] && map[cur[0]][cur[1]+1]>=0) {
				isV[cur[0]][cur[1]+1]=true;
				qu.offer(new int[] {cur[0], cur[1]+1, cur[2]+1});
			}
			if(!isV[cur[0]][cur[1]-1] && map[cur[0]][cur[1]-1]>=0) {
				isV[cur[0]][cur[1]-1]=true;
				qu.offer(new int[] {cur[0], cur[1]-1, cur[2]+1});
			}
			
		}
		
		return dist;
	}
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

 

'알고리즘 문제 풀이 > BOJ 골드' 카테고리의 다른 글

[백준] 2096 - 내려가기  (0) 2021.04.16
[백준] 15961 - 회전 초밥  (0) 2021.04.15
[백준] 2638 - 치즈  (0) 2021.04.15
[백준] 9935 - 문자열 폭발  (0) 2021.04.14
[백준] 1019 - 책 페이지  (0) 2021.04.13
[백준] 1566 - P배열  (0) 2021.04.13
[백준] 12865 - 평범한 배낭  (0) 2021.04.12

[문제링크]

 

SW Expert Academy

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

swexpertacademy.com

 

0. shoot함수 : n번째 구슬을 모든 경우의 수에 대해 쏴보고, n+1번째로 재귀하는 함수

  - remove함수 : x, y좌표의 벽돌이 깨졌을 경우 모든 벽돌을 재귀로 깨는 함수

  - getDown함수 : 벽돌을 깬 후 모든 벽돌을 빈공간 없이 아래로 쌓는 함수

 

1. shoot함수가 모든 경우의 수에 대해 remove -> getDown 해본다

 

2. n번 구슬을 쐈을때 남아있는 ball값과 min을 비교, 갱신

 

* ball(remain)값을 인자로 넘기지 말고 전역변수로 관리할 수 있을것같은데, 피곤해서 포기

 

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

public class Solution{
	
	static int n,w,h,ball,min;
	static int[][]map;
	static int[] dx = {1,0,-1,0};
	static int[] dy = {0,1,0,-1};
	
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		
		int tc = pint(br.readLine());
		for (int testcase = 1; testcase <= tc; testcase++) {
			StringTokenizer st = new StringTokenizer(br.readLine(), " ");
			n = pint(st.nextToken());
			w = pint(st.nextToken());
			h = pint(st.nextToken());
			ball = 0;
			map = new int[h][w];
			
			for (int i = 0; i < h; i++) {
				st = new StringTokenizer(br.readLine());
				for (int j = 0; j < w; j++) {
					map[i][j]=pint(st.nextToken());
					if(map[i][j]!=0)ball++;
				}
			}
			min=ball;
			shoot(0,ball);
			
			sb.append("#").append(testcase).append(" ").append(min).append("\n");
		}
		System.out.println(sb);
	}
	
	static void shoot(int cnt, int remain) {
		if(cnt==n) {
			min=Math.min(min, remain);
			return;
		}
		//현재 정보 백업
		int[][]backup = new int[h][w];
		for (int x = 0; x < h; x++) {
			for (int y = 0; y < w; y++) {
				backup[x][y]=map[x][y];
			}
		}
		int ballBackup=ball;

		for (int i = 0; i < w; i++) {
			// 정보 원상복구
			for (int x = 0; x < h; x++) {
				for (int y = 0; y < w; y++) {
					map[x][y]=backup[x][y];
				}
			}
			ball=ballBackup;

			for (int j = 0; j < h; j++) {
				if(map[j][i]!=0) {
					remove(j,i); // 제거하고
					getDown(); // 아래로 정렬하고
					break;
				}
			}
			shoot(cnt+1, ball); // 다음 발사로 재귀
			
		}
	}
	
	static void remove(int x, int y) {
		int c = map[x][y];
		map[x][y]=0;
		--ball;
		for (int j = 0; j < 4; j++) {
			int tx=x, ty=y;
			for (int i = 1; i < c; i++) {
				tx += dx[j];
				ty += dy[j];
				if(tx<0 || tx>=h || ty<0 || ty>=w)break;
				if(map[tx][ty]!=0)remove(tx,ty);
			}
		}
	}
	
	static void getDown() {
		for (int i = 0; i < w; i++) {
			int cnt=h-1;
			for (int j = h-1; j >=0 ; j--) {
				if(map[j][i]!=0) {
					int t = map[j][i];
					map[j][i]=0;
					map[cnt--][i]=t;
				}
			}
		}
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

+ Recent posts