https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5PobmqAPoDFAUq&categoryId=AV5PobmqAPoDFAUq&categoryType=CODE

 

SW Expert Academy

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

www.swexpertacademy.com

방향 전환 문제 연습하기 좋은 문제 같다.

 

풀이

  1. 먼저 N이 1일 때는 2차원 배열을 만들지 못하므로 바로 1을 출력하도록 처리해주었다.
  2. 우 -> 하 -> 좌 -> 상 순서로 계속 움직일 것이므로 미리 순서에 맞게 dx, dy 배열을 저장.
  3. 처음 좌표는 (0,0) 방향은 dir=0 (우 방향)
  4. i부터 N*N까지 순차적으로 저장해준다.
  5. 범위를 벗어나거나 이동할 곳에 값이 이미 있는 경우마다 방향을 회전해준다.
    1. 좌표를 다시 원래대로 돌려준 후에
    2. 방향 전환하고
    3. 다시 전환한 방향으로 이동

 

import java.io.*;

public class Solution {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		int dx[] = {0,1,0,-1};
		int dy[] = {1,0,-1,0};
		for(int tc=1; tc<=T; tc++) {
			int N = Integer.parseInt(br.readLine());
			
            //N 이 1인 경우를 따로 처리
			if(N == 1) {
				System.out.println("#"+tc);
				System.out.println(1);
				continue;
			}
			int[][] arr = new int[N][N];
           
			int x = 0;
			int y = 0;
			int dir = 0; //처음 방향은 0(우 방향)
			
            
			for(int i=0; i<N*N; i++) {
				
				arr[x][y] = i+1;
				x += dx[dir];
				y += dy[dir];
                
                //범위를 벗어나는 경우 방향 전환
				if(x >= N || y >= N || x < 0 || y < 0) {
					//원래 위치로 돌려주고
                    x -= dx[dir];
					y -= dy[dir];
                    
                    //방향 전환 (0->1 우에서 하/ 1->2 하에서 좌/ 2->3 좌에서 상/ 3->0 상에서 우)
					dir = (dir+1)%4;
                    
                    //전환한 방향으로 이동
					x += dx[dir];
					y += dy[dir];
				}
				
                //이동할 곳에 값이 있는 경우 방향 전환
				if(arr[x][y] != 0) {
					x -= dx[dir];
					y -= dy[dir];
					dir = (dir+1)%4;
					x += dx[dir];
					y += dy[dir];
				}
				
			}
			
			System.out.println("#"+tc);
			for(int i=0; i<N; i++) {
				for(int j=0; j<N; j++) {
					System.out.print(arr[i][j]+" ");
				}
				System.out.println();
			}
		}
	}

}

'SWEA > D2' 카테고리의 다른 글

[SWEA] 1946. 간단한 압축 풀기  (0) 2019.05.14
[SWEA] 1948. 날짜 계산기  (0) 2019.05.14
[SWEA] 1959. 두 개의 숫자열  (0) 2019.05.14
[SWEA] 1961. 숫자 배열 회전  (0) 2019.05.14
[SWEA] 1974. 스도쿠 검증  (0) 2019.05.03

https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5PpoFaAS4DFAUq&categoryId=AV5PpoFaAS4DFAUq&categoryType=CODE

 

SW Expert Academy

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

www.swexpertacademy.com

풀이

  1. N < M 인 경우 / N == M 인 경우 / N > M 인경우로 나눠서 풀었다.
  2. 자세한 설명은 코드에 추가했다.

 

import java.io.*;
import java.util.*;

public class Solution {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		

		for(int tc=1;tc<=T;tc++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			int N = Integer.parseInt(st.nextToken());
			int M = Integer.parseInt(st.nextToken());
			
			int[] a = new int[N];
			int[] b = new int[M];
			
			st = new StringTokenizer(br.readLine());
			for(int i=0; i<N; i++) {
				a[i] = Integer.parseInt(st.nextToken());
			}
			
			st = new StringTokenizer(br.readLine());
			for(int j=0; j<M; j++) {
				b[j] = Integer.parseInt(st.nextToken());
			}
			
			int max = 0;
			int tmp = 0;
			if(N < M) {
				
				for(int j=0; j<=M-N; j++) { //인덱스가 M-N을 넘어가면 비교할 범위(N개)가 넘어가므로
					int k=j; //비교할 위치
					int sum = 0;
					for(int i=0; i<N; i++) { //N개만큼동안 a배열과 b배열의 값을 곱해준다.
						tmp = a[i] * b[k++]; //a배열값과 b배열값 곱해주기
						sum += tmp; //곱한 값을 계속 더해준다.
					}
					if(sum > max) max = sum; //최댓값을 저장
				}

			} else if(N == M) { //크기가 같은 경우에 최댓값의 경우는 한가지.
				for(int i=0; i<N; i++) {
					max += a[i]*b[i];
				}
			} else { // N이 더 큰 경우. M이 더 큰 경우와 반대로 해주면 된다.
				for(int j=0; j<=N-M; j++) {
					int k=j;
					int sum = 0;
					for(int i=0; i<M; i++) {
						tmp = a[k++] * b[i];
						sum += tmp;
					}
					if(sum > max) max = sum;
				}
			}
			
			System.out.println("#"+tc+" "+max);
		}
	}

}

'SWEA > D2' 카테고리의 다른 글

[SWEA] 1948. 날짜 계산기  (0) 2019.05.14
[SWEA] 1954. 달팽이 숫자  (0) 2019.05.14
[SWEA] 1961. 숫자 배열 회전  (0) 2019.05.14
[SWEA] 1974. 스도쿠 검증  (0) 2019.05.03
[SWEA] 1970. 쉬운 거스름돈  (0) 2019.05.03

https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5Pq-OKAVYDFAUq&categoryId=AV5Pq-OKAVYDFAUq&categoryType=CODE

 

SW Expert Academy

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

www.swexpertacademy.com

풀이

  1. 입력받은 배열을 처음에 90도 돌려서 새로운 배열에 저장해준다.
  2. 위에도 90도 돌린 배열을 다시 돌리면 180도가 되고 다시 이 배열을 돌리면 270도가 된다.
  3. 90도씩 회전하는 rotate함수
    1. 새로운 배열에 배열을 돌려서 저장한 후에 새로운 배열을 리턴한다.
    2. 90도를 돌리면 1행이 N열로, 2행이 N-1열로, ,,, , N행이 1열로 된다.
    3. 새로운 배열에서 N열부터 감소해가며 모든 열을 채워준다.
    4. 각 열에서는 1행부터 순서대로 채워준다.
import java.io.*;
import java.util.*;

public class Solution {
	static int N;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		
		for(int tc=1; tc<=T; tc++) {
			N = Integer.parseInt(br.readLine());
			int[][] arr = new int[N][N];
			
			StringTokenizer st;
			for(int i=0; i<N; i++) {
				st = new StringTokenizer(br.readLine());
				for(int j=0; j<N; j++) {
					arr[i][j] = Integer.parseInt(st.nextToken());
				}
			}
			
            //기존의 배열을 90도 회전
			int[][] arr90 = rotate(arr);
            
            //90도 회전한 배열을 다시 90도 회전 == 180도 회전
			int[][] arr180 = rotate(arr90);
            
            //180도 회전한 배열을 다시 90도 회전 == 270도 회전
			int[][] arr270 = rotate(arr180);
						
                        
			System.out.println("#"+tc);
			for(int i=0; i<N; i++) {
            
            	//90도 회전 배열 출력
				for(int j=0; j<N; j++) {
					System.out.print(arr90[i][j]);
				}
				System.out.print(" ");
                
                //180도 회전 배열 출력
				for(int j=0; j<N; j++) {
					System.out.print(arr180[i][j]);
				}
				System.out.print(" ");
                
                //270도 회전 배열 출력
				for(int j=0; j<N; j++) {
					System.out.print(arr270[i][j]);
				}
				System.out.println();
			}
		}

	}
	
	
	//90도 회전시키는 함수
	static int[][] rotate(int[][] arr) {
    
		int[][] newarr = new int[N][N]; //새로운 배열에다 회전한 값을 넣어준다.
		int k = 0; //기존 배열의 행을 가르키는 index
        
		for(int j=N-1; j>=0; j--) {
			for(int i=0; i<N; i++) {
            	//새로운 배열에는 마지막 열(N-1)부터, 각 열에서는 첫 행(0)부터 채워준다.
                //기존 배열의 k행 i열값을 넣어준다. (0행0열부터 순차대로 넣어준다)
				newarr[i][j] = arr[k][i];
			}
			k++;
		}
		
		return newarr;
	}

}

'SWEA > D2' 카테고리의 다른 글

[SWEA] 1954. 달팽이 숫자  (0) 2019.05.14
[SWEA] 1959. 두 개의 숫자열  (0) 2019.05.14
[SWEA] 1974. 스도쿠 검증  (0) 2019.05.03
[SWEA] 1970. 쉬운 거스름돈  (0) 2019.05.03
[SWEA] 1979. 어디에 단어가 들어갈 수 있을까  (0) 2019.05.02

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

 

SW Expert Academy

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

www.swexpertacademy.com

풀이

  1. 먼저 사용자들의 이동 정보를 각 배열에 저장하고 BC의 정보는 AP클래스를 만들어서 ArrayList에 저장하였다.
  2. 시간에 따라 이동하면서 각 시간마다 A와 B의 충전량 합의 최댓값을 구해준다.
    1. 최댓값은 사용자가 각각 사용할 수 있는 충전량을 배열에 저장해놓고 모든 경우를 구해줬다.
    2. 이때 i == j 인 상황이 됐을 때 한쪽은 0 (해당 BC를 사용할 수 없는 경우)일 수도 있으므로 무조건 반으로 나눠주면 안 되고 둘 다 해당 BC를 이용하고 있는지 확인해주어야 한다. (같은 p값을 가지는지 확인)
  3. 시간마다의 최댓값을 모두 더해준 후에 출력

 

import java.io.*;
import java.util.*;

public class Solution {
	static class AP {
		int x;
		int y;
		int c;
		int p;
		AP(int x, int y, int c, int p) {
			this.x = x;
			this.y = y;
			this.c = c;
			this.p = p;
		}
	}
	
	static int M,A;
	static int dx[] = {0,-1,0,1,0};
	static int dy[] = {0,0,1,0,-1};
	static int Ainfo[];
	static int Binfo[];
	static ArrayList aplist;
    
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		
		for(int tc=1; tc<=T; tc++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			M = Integer.parseInt(st.nextToken());
			A = Integer.parseInt(st.nextToken());
			Ainfo = new int[M];
			Binfo = new int[M];
			
            //사용자 A의 이동정보
			st = new StringTokenizer(br.readLine());
			for(int i=0; i<M; i++) {
				Ainfo[i] = Integer.parseInt(st.nextToken());
			}
			
            //사용자 B의 이동정보
			st = new StringTokenizer(br.readLine());
			for(int i=0; i<M; i++) {
				Binfo[i] = Integer.parseInt(st.nextToken());
			}
			
            //BC의 정보를 ArrayList에 저장한다.
			aplist = new ArrayList();
			for(int i=0; i<A; i++) {
				st = new StringTokenizer(br.readLine());
				
				int y = Integer.parseInt(st.nextToken());
				int x = Integer.parseInt(st.nextToken());
				int c = Integer.parseInt(st.nextToken());
				int p = Integer.parseInt(st.nextToken());
				
				aplist.add(new AP(x,y,c,p));
			}
			
			int ans = move();
			System.out.println("#"+tc+" "+ans);
		}
	}
	
    
	static int move() {
		int x1 = 1;
		int y1 = 1;
		int x2 = 10;
		int y2 = 10;
        
        //0초일때의 합
		int sum = getMax(x1,y1,x2,y2);
		
        //시간별로 이동하면서 그때마다의 최대값을 합해준다.
		for(int time=0; time<M; time++) {
			x1 += dx[Ainfo[time]];
			y1 += dy[Ainfo[time]];
			x2 += dx[Binfo[time]];
			y2 += dy[Binfo[time]];
			sum += getMax(x1,y1,x2,y2);
		}
		
		return sum;
	}
	
    
	static int getMax(int x1, int y1, int x2, int y2) {
		int[][] amount = new int[2][A];
		//2차원 배열에 사용자A(0)와 사용자B(1)의 BC별로 충전가능한 값을 저장해준다.
        
        //사용자A의 충전 가능한 BC의 p값
		for(int j=0; j<A; j++) {
				amount[0][j] = check(x1,y1,j);
		}
		
        //사용자B의 충전 가능한 BC의 p값
		for(int j=0; j<A; j++) {
			amount[1][j] = check(x2,y2,j);
			
		}
		
        //사용자 A와 사용자 B의 충전량의 합중 최댓값을 구해준다.
		int max = 0;
		for(int i=0; i<A; i++) {
			for(int j=0; j<A; j++) {
				int sum = amount[0][i]+amount[1][j];
                
                 // 같은 BC를 이용하는 경우 값을 반으로 나눠줘야한다.
                 // 주의할 점은 한 쪽은 아예 값이 0일수도 있으므로(해당 BC를 이용할 수 없는 위치) 정확히 둘다 같이 이용하고 있는 경우에만 나누어주어야한다.
				if(i == j && amount[0][i] == amount[1][j])
					sum /= 2;
				if(sum > max) max = sum;
			}
		}

		return max;
	}
	
	static int check(int x, int y, int apnum) {

		int a = Math.abs(x-aplist.get(apnum).x);
		int b = Math.abs(y-aplist.get(apnum).y);
		int dist = a+b;
        
        //해당 BC에 포함되는 경우에 p값을 리턴
		if(dist <= aplist.get(apnum).c)
			return aplist.get(apnum).p;
		else
			return 0;
	}
	
}

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

 

SW Expert Academy

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

www.swexpertacademy.com

1. 1 ≤ N  4

2. 2 ≤ W  12

3. 2 ≤ H  15

범위가 위와 같기 때문에 완전 탐색을 해주면 된다. 연쇄적으로 깨질 벽돌은 큐를 사용하여 관리해줬다.

 

풀이

  1. 벽돌을 깨는 경우를 모든 열에 대해서 구해준다.
  2. 열을 선택하면 그 열에서 구슬에 처음 닿을 벽돌(행)을 찾아준다.
  3. 이제 위에서 찾은 벽돌에서부터 해당 칸의 값-1만큼 연쇄적으로 깨 주고 빈 공간을 채워주어야 한다.
    1. 먼저 새로 배열을 만들어야 한다. (매번 깨지는 모양이 다르므로)
    2. 깨뜨릴 벽돌들(값이 2 이상)의 정보를 큐에 넣어주고 매번 큐에서 꺼내서 깨뜨린다. (값이 0인 경우는 그냥 넘어가고 1인 경우에는 해당 칸을 0으로 만든 후 넘어간다)
    3. 큐에 있는 벽돌들을 제거해줬으면 이제 빈 공간을 정리해준다.
  4. 빈칸을 채울 때는 모든 열에서 마지막 행부터 순차적으로 검사한다.
    1. 0인 곳(비어있는 곳)을 찾아서 더 위칸에서 0이 아닌 값을 찾아 옮겨준다.
    2. 위쪽 칸들이 모두 0인 경우에는 다음 열로 넘어간다.
  5. 다음 구슬을 쏘기 위해서 구슬을 쏜 횟수인 cnt값을 증가시킨 후 위의 과정을 반복한다.
  6. cnt값이 N이 되었다면 남은 벽돌의 최소 개수를 구해준다.
  7. 최솟값을 출력하거나 벽돌이 모두 깨져서 최솟값을 계산해주지 못하고 초기값인 경우에는 0을 출력한다.

 

import java.io.*;
import java.util.*;

public class Solution {

	static class Pair {
		int x;
		int y;
		int num;
		Pair(int x, int y, int num) {
			this.x = x;
			this.y = y;
			this.num = num;
		}
	}
	
	static int N,W,H,min;
	static Queue q;
	static int[] dx = {1,-1,0,0};
	static int[] dy = {0,0,1,-1};
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		for(int tc=1; tc<=T; tc++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			N = Integer.parseInt(st.nextToken());
			W = Integer.parseInt(st.nextToken());
			H = Integer.parseInt(st.nextToken());
			
			int[][] 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] = Integer.parseInt(st.nextToken());
				}
			}
            
			min = -1;
			solve(0,map);
            
			if(min == -1) //벽돌이 모두 깨진 경우
				System.out.println("#"+tc+" "+0);
			else
				System.out.println("#"+tc+" "+min);
		}
	}
	
    
	static void solve(int cnt, int[][] arr) {
		if(cnt == N) {
			int remain = 0;
			for(int i=0; i<H; i++) {
				for(int j=0; j<W; j++) {
					if(arr[i][j] != 0)
						remain++;
				}
			}
            
			if(min == -1 || min > remain)
				min = remain;	
			return;
		}
		
        //모든 열에 대하여 구슬을 쏘는 경우를 구해준다.
		for(int j=0; j<W; j++) {
			int i = 0;
			while(i < H) {
				if(arr[i][j] != 0) break;
				i++;
			}
			
			if(i == H) continue; //해당 열이 모두 빈칸이라 다음 열로 넘어간다.
			
			int[][] arr2 = copyArr(arr);
			crush(i,j,arr2); //깨뜨리기
			move(arr2); // 빈 칸 정리
			solve(cnt+1,arr2); // 다음 구슬 쏘기
		}
	}
	
    
	static void move(int[][] arr) {
		for(int j=0; j<W; j++) {
			for(int i=H-1; i>0; i--) {	
				if(arr[i][j] == 0) {
                	//빈 칸을 찾으면 해당 빈칸 보다 위쪽 칸을 검사한다.
					int k = i-1;
					while(k >= 0) {
						if(arr[k][j] != 0) { //떠 있는 벽돌(빈 칸이 아닌 칸)을 발견하면
							arr[i][j] = arr[k][j]; //아래로 옮겨주고
							arr[k][j] = 0; //해당칸은 비워준다.
							break;
						}
						k--; //위쪽 칸을 계속 검사
					}
					if(k == -1) break; // 위쪽칸들이 모두 0인 경우 해당 열을 더 검사할 필요가 없으므로 다음 열로 넘어간다.
				}
			}
		}
	}
	
    
	static void crush(int x, int y, int[][] arr) {
		q = new LinkedList();
		q.add(new Pair(x,y,arr[x][y]));
		arr[x][y] = 0;
		
		while(!q.isEmpty()) {
			Pair p = q.remove();
			for(int i=0; i<4; i++) {
				int nx = p.x;
				int ny = p.y;
				int num = p.num;
				for(int j=0; j<num-1; j++) {
					nx += dx[i];
					ny += dy[i];
					if(nx < 0 || nx >= H || ny < 0 || ny >= W) break;
					if(arr[nx][ny] == 0) continue;					
					if(arr[nx][ny] > 1)
						q.add(new Pair(nx,ny,arr[nx][ny]));
					arr[nx][ny] = 0; //깨트리기	
				}
	
			}
		}
	}
	
    
	static int[][] copyArr(int[][] arr) {
		int[][] newArr = new int[H][W];
		for(int i=0; i<H; i++) {
			for(int j=0; j<W; j++) {
				newArr[i][j] = arr[i][j];
			}
		}
		return newArr;
	}

}

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

 

SW Expert Academy

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

www.swexpertacademy.com

이번에는 두 가지 방법으로 풀어보았다. 사실 첫 번째 풀이(BFS)로 풀고 다른 사람들 실행 시간과 비교해봤을때 엄청 빠르게 푼 사람이 있어서 다른 사람들 풀이 좀 찾아보고 다시 풀어봤다ㅠㅠ 두 번째 풀이가 훨씬 빠를 뿐만아니라 메모리 차이도 엄청나다...

 

 

두 번째 풀이
첫 번째 풀이

 

첫 번째 풀이 (BFS 풀이)

  1. K 값이 커질 때마다 BFS가 단계별로 진행하는 모양과 같기 때문에 BFS로 풀었다.
  2. N의 범위가 (5 ≤ N ≤ 20) 이므로 완전 탐색을 해줬다.
  3. 모든 칸에 대해서 bfs를 통해 서비스 영역 모양 처럼 퍼지도록 계산해줬다.
  4. K 값이 증가할때마다 서비스를 받는 집의 수를 계산하고 최댓값을 저장한다.
    1. K 값이 바뀌는 것은 큐 사이즈를 저장해놨다가 큐 사이즈 만큼을 진행해주고 나면된다.
    2. 예를 들어 K=1 일때 큐 size 는 1이고 K=2 일때 size는 4, K=4 일때 size = 8 이다.
    3. K 값이 바뀔 때마다 calc 함수에서 최대 서비스할 수 있는 집의 개수를 세서 리턴한다.
import java.io.*;
import java.util.*;

public class Solution {
	static class Pair {
		int x;
		int y;
		Pair(int x, int y) {
			this.x = x;
			this.y = y;
		}
	}
	
	static int N,M,max;
	static int[] dx = {0,0,1,-1};
	static int[] dy = {1,-1,0,0};
	static int[][] city;
	static Queue q = new LinkedList();
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		for(int tc=1; tc<=T; tc++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			N = Integer.parseInt(st.nextToken());
			M = Integer.parseInt(st.nextToken());
			
			city = new int[N][N];
			for(int i=0; i<N; i++) {
				st = new StringTokenizer(br.readLine());
				for(int j=0; j<N; j++) {
					city[i][j] = Integer.parseInt(st.nextToken());
				}
			}
			
			max = 0;
            
            //모든칸 탐색
			for(int i=0; i<N; i++) {
				for(int j=0; j<N; j++) {
					bfs(i,j);
				}
			}
			
			System.out.println("#"+tc+" "+max);
		}
	}
	
	static void bfs(int i, int j) {
		
		boolean check[][] = new boolean[N][N];
		q.add(new Pair(i,j));
		check[i][j] = true;
		int homecnt = 0;
		int k = 1;
		int size = q.size(); //처음 큐 사이즈 저장( 1값을 저장)
		while(!q.isEmpty()) {
			
			//K 값이 증가할 때마다 서비스를 받는 집의 수를 계산하고 최댓값을 저장한다.
			homecnt = calc(k++, check);
			if(max < homecnt) {
				max = homecnt;
			}
			
			size = q.size(); //단계별로 진행하기 위해서 매번 들어가있는 큐사이즈를 구해준다
			while(size-- > 0) { //size 만큼 탐색 진행
				Pair p = q.remove();
				int x = p.x;
				int y = p.y;

				int cnt = 0;
				for(int l=0; l<4; l++) {
					int nx = x+dx[l];
					int ny = y+dy[l];
					if(nx < 0 || nx >= N || ny < 0 || ny >= N) continue;
					if(check[nx][ny]) continue;
					q.add(new Pair(nx,ny));
					check[nx][ny] = true;
					if(city[nx][ny] == 1) cnt+= 1;
				}
			}
			
			
		}
	}
	
	static int calc(int k, boolean[][] check) {
		int homecnt = 0;
		for(int i=0; i<N; i++) {
			for(int j=0; j<N; j++) {
				if(check[i][j] && city[i][j] == 1) {
					homecnt += 1; //방문 한 곳(서비스 영역)중에 집이 있으면 집의 수를 count
				}
			}
		}
		
		int cost = (k*k)+((k-1)*(k-1));
		int profit = homecnt*M - cost;
		if(profit >= 0) //마이너스 값이 아닌 이상 손해가 아니다
			return homecnt;
		else
			return 0;
	}

}

 

 

두 번째 풀이

  1. 모든칸에 대해서 K값에 따른 최대 집의 개수를 구해준다.
  2. 집의 K값의 모양을 구하는식은
    1. 현재 칸이 x, y 라고 했을 때 모든 칸 i, j 에 대해서 계산해준다.
    2. K = |i-x| + |j-y|  를 계산해서 다음과 같이 구할 수 있다.
  3. K=2 일때 위의 식을 사용하면 다음과 같이 된다.
    2    
  2 1 2  
2 1 (x,y) 1 2
  2 1 2  
    2    

 

import java.io.*;
import java.util.*;

public class Solution {

	static int N,M,max;
	static int[][] city;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		for(int tc=1; tc<=T; tc++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			N = Integer.parseInt(st.nextToken());
			M = Integer.parseInt(st.nextToken());
			
			city = new int[N][N];
			for(int i=0; i<N; i++) {
				st = new StringTokenizer(br.readLine());
				for(int j=0; j<N; j++) {
					city[i][j] = Integer.parseInt(st.nextToken());
				}
			}
			
			max = 0;
			for(int i=0; i<N; i++) {
				for(int j=0; j<N; j++) {
					calc(i,j);
				}
			}
			
			System.out.println("#"+tc+" "+max);
		}
	}
	
	static void calc(int x, int y) {
        for (int k = 0; k < N + 2; k++) {
        	//K가 최대 N*N 칸을 모두 채우는 범위까지 진행
            int homecnt = 0;
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    int nx = Math.abs(i - x);
                    int ny = Math.abs(j - y);
                    if (nx + ny < k && city[i][j] == 1) {
                    	//현재 K 일때의 서비스 영역이고, 집이 있으면 집의 수를 count 해준다.
                        homecnt++;
                    }
                }
            }
            int profit = (homecnt * M) - (k * k + (k - 1) * (k - 1)); //수익 계산
            if (profit < 0)
                continue;
            else
                max = Math.max(homecnt, max); //손해를 보지 않으면 집의 수를 최댓값과 비교하여 더 크면 저장.
        }
    }
	

}

https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5Psz16AYEDFAUq&categoryId=AV5Psz16AYEDFAUq&categoryType=CODE

 

SW Expert Academy

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

www.swexpertacademy.com

 

풀이

    1. 가로, 세로, 3X3격자칸을 검사하는 함수를 각각 만들어주었다.
    2. 검사 중 하나라도 겹치는 숫자를 가지고 있다면 0을 출력하고 다음 테스트 케이스로 넘어간다.
    3. 각 check함수에서는 check 배열을 만들어서 해당 숫자칸이 이미 true이면 false를 리턴한다. 그렇지 않으면 check배열의 해당 인덱스 값을 true로 바꿔준다.
    4. 격자칸의 경우 각 격자칸의 시작점(0,0), (0,3), (0,6), (3,0), ,,, ,(6,6),(6,9) 에서 부터 시작하여 3X3칸을 검사하도록 했다.
import java.io.*;
import java.util.StringTokenizer;

public class Solution {

	static int[][] puzzle;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
        
		for(int tc=1; tc<=T; tc++) {
			puzzle = new int[9][9];
            
			for(int i=0; i<9; i++) {
				StringTokenizer st = new StringTokenizer(br.readLine());
				for(int j=0; j<9; j++) {
					puzzle[i][j] = Integer.parseInt(st.nextToken());
				}
			}
			
            
			boolean flag = true;
            //모든 가로를 검사한다.
			for(int i=0; i<9; i++) {
				if(!checkGaro(i)) {
                	//한줄이라도 false이면 검사를 멈춘다.
					System.out.println("#"+tc+" "+0);
					flag = false;
					break;
				}
			}
			if(!flag) continue; //다음 테스트 케이스 실행
			
            
            //모든 세로를 검사
			for(int j=0; j<9; j++) {
				if(!checkSero(j)) {
					System.out.println("#"+tc+" "+0);
					flag = false;
					break;
				}
			}
			if(!flag) continue; //다음 테스트 케이스 실행
			
            
            //모든 3X3 격자칸 검사
            //격자칸의 각 시작점에서부터 검사
			for(int i=0; i<=6; i+=3) { //3칸씩 점프 (다음 격자칸 이동을 위해)
				for(int j=0; j<=6; j+=3) {
					if(!checkNemo(i,j)) {
						System.out.println("#"+tc+" "+0);
						flag = false;
						break;
					}
				}
				if(!flag) break;
			}
			if(!flag) continue;
			
            
            //위에서 모두 검사를 통과했다면 1을 출력
			System.out.println("#"+tc+" "+1);
			
		}
	}
	
    
	static boolean checkGaro(int x) {
		boolean[] check = new boolean[9];
		for(int j=0; j<9; j++) { // x행에 대하여 모든 j열을 검사.
			if(check[puzzle[x][j]-1]) //이미 해당 숫자를 가지고 있다.
				return false;
			check[puzzle[x][j]-1] = true;
		}
		
		return true;
	}
	
    
	static boolean checkSero(int y) {
		boolean[] check = new boolean[9];
		for(int i=0; i<9; i++) { // y열에 대하여 모든 i행을 검사.
			if(check[puzzle[i][y]-1]) //이미 해당 숫자를 가지고 있다.
				return false;
			check[puzzle[i][y]-1] = true;
		}
		return true;
	}
	
    
	static boolean checkNemo(int x, int y) {
		boolean[] check = new boolean[9];
		int nx = x+3;
		int ny = y+3;
        //x행 y열에서 시작하는 3X3 칸을 검사.
		for(int i=x; i<nx; i++) {
			for(int j=y; j<ny; j++) {
				if(check[puzzle[i][j]-1]) //이미 해당 숫자를 가지고 있다.
					return false;
				check[puzzle[i][j]-1] = true;
			}
		}
		return true;
	}


}

'SWEA > D2' 카테고리의 다른 글

[SWEA] 1959. 두 개의 숫자열  (0) 2019.05.14
[SWEA] 1961. 숫자 배열 회전  (0) 2019.05.14
[SWEA] 1970. 쉬운 거스름돈  (0) 2019.05.03
[SWEA] 1979. 어디에 단어가 들어갈 수 있을까  (0) 2019.05.02
[SWEA] 1976. 시각 덧셈  (0) 2019.05.02

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

 

SW Expert Academy

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

www.swexpertacademy.com

풀이

화폐단위를 미리 배열에 넣어두고 차례대로 나눠주며 count를 해줬다.

import java.io.*;


public class Solution {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		for(int tc=1; tc<=T; tc++) {
			int N = Integer.parseInt(br.readLine());
			
			int[] count = new int[8];
			int[] money = {50000, 10000, 5000, 1000, 500, 100, 50, 10};
			for(int i=0; i<8; i++) {
				if(N >= money[i]) { //돈이 화폐단위보다 같거나 클때만 나눠준다.
					int cnt = N/money[i];
					count[i] = cnt;
					N -= cnt*money[i];
				}
			}
			
			System.out.println("#"+tc);
			for(int i=0; i<8; i++) {
				System.out.print(count[i]+" ");
			}
			System.out.println();
		}
	}

}

'SWEA > D2' 카테고리의 다른 글

[SWEA] 1961. 숫자 배열 회전  (0) 2019.05.14
[SWEA] 1974. 스도쿠 검증  (0) 2019.05.03
[SWEA] 1979. 어디에 단어가 들어갈 수 있을까  (0) 2019.05.02
[SWEA] 1976. 시각 덧셈  (0) 2019.05.02
[SWEA] 1983. 조교의 성적 매기기  (0) 2019.05.01

+ Recent posts