https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5V61LqAf8DFAWu
SW Expert Academy
SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!
www.swexpertacademy.com
이번에는 두 가지 방법으로 풀어보았다. 사실 첫 번째 풀이(BFS)로 풀고 다른 사람들 실행 시간과 비교해봤을때 엄청 빠르게 푼 사람이 있어서 다른 사람들 풀이 좀 찾아보고 다시 풀어봤다ㅠㅠ 두 번째 풀이가 훨씬 빠를 뿐만아니라 메모리 차이도 엄청나다...


첫 번째 풀이 (BFS 풀이)
- K 값이 커질 때마다 BFS가 단계별로 진행하는 모양과 같기 때문에 BFS로 풀었다.
- N의 범위가 (5 ≤ N ≤ 20) 이므로 완전 탐색을 해줬다.
- 모든 칸에 대해서 bfs를 통해 서비스 영역 모양 처럼 퍼지도록 계산해줬다.
- K 값이 증가할때마다 서비스를 받는 집의 수를 계산하고 최댓값을 저장한다.
- K 값이 바뀌는 것은 큐 사이즈를 저장해놨다가 큐 사이즈 만큼을 진행해주고 나면된다.
- 예를 들어 K=1 일때 큐 size 는 1이고 K=2 일때 size는 4, K=4 일때 size = 8 이다.
- 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;
}
}
두 번째 풀이
- 모든칸에 대해서 K값에 따른 최대 집의 개수를 구해준다.
- 집의 K값의 모양을 구하는식은
- 현재 칸이 x, y 라고 했을 때 모든 칸 i, j 에 대해서 계산해준다.
- K = |i-x| + |j-y| 를 계산해서 다음과 같이 구할 수 있다.
- 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); //손해를 보지 않으면 집의 수를 최댓값과 비교하여 더 크면 저장.
}
}
}
'SWEA > 모의 SW 역량테스트(JAVA)' 카테고리의 다른 글
| [SWEA] 4013. [모의 SW 역량테스트] 특이한 자석 (0) | 2019.05.15 |
|---|---|
| [SWEA] 5644. 무선 충전 (0) | 2019.05.10 |
| [SWEA] 5656. 벽돌 깨기 (0) | 2019.05.10 |
| [SWEA] 1949. 등산로 조성 (0) | 2019.05.01 |
| [SWEA] 5658. 보물상자 비밀번호 (0) | 2019.04.30 |