반응형

문제 출처

https://programmers.co.kr/learn/courses/30/lessons/17680

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제풀이

도시이름을 소문자로 모두 바꾼뒤 풀이해야한다. cache 벡터를 사용해서 사용해서 매개변수로 주어진 cacheSize보다 크거나 같을 때 가장 앞에 있는 원소를 삭제해주면 된다. 문제에서 시키는데로 그냥 구현하면 되는 문제.

 

소스코드

https://github.com/sw93/algorithm/blob/master/Programmers/kakao2018%20-%20%EC%BA%90%EC%8B%9C.cpp

 

sw93/algorithm

problem solve. Contribute to sw93/algorithm development by creating an account on GitHub.

github.com

#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
int solution(int cacheSize, vector<string> cities) {
    int answer = 0;
    vector<string> cache;
    if (cacheSize == 0) {
        return cities.size() * 5;
    }
    
    for (int i=0; i<cities.size(); i++) {
        transform(cities[i].begin(), cities[i].end(), cities[i].begin(), ::tolower);
        vector<string>::iterator it = find(cache.begin(), cache.end(), cities[i]);
        if (it == cache.end()) {
            if (cache.size() >= cacheSize) cache.erase(cache.begin());
            cache.push_back(cities[i]);
            answer+=5;
        } else {
            cache.erase(it);
            cache.push_back(cities[i]);
            answer++;
        }
    }
    return answer;
}
반응형
반응형

문제 출처

https://programmers.co.kr/learn/courses/30/lessons/17682

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제 풀이

if else문을 떡칠해서 풀이했다. 단순히 문제의 조건에 따라 구현해주면 되는 문제라 어렵지 않았다. 단지 이 문제에서 가장 중요했던 점은 2번 조건인 '각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.' 이 문항이다.

dartResult의 1자리씩 끊어서 보다보니까 10이 나온경우 for문의 반복변수를 1개 추가해줘야하기 때문이다.

 

소스 코드

https://github.com/sw93/algorithm/blob/master/Programmers/kakao2018%20-%20%EB%B9%84%EB%B0%80%EC%A7%80%EB%8F%84.cpp

 

sw93/algorithm

problem solve. Contribute to sw93/algorithm development by creating an account on GitHub.

github.com

#include <string>
#include <cmath>
#include <vector>
using namespace std;
int solution(string dartResult) {
    int answer = 0, index = -1;
    vector<int> score;
    for (int i=0; i<dartResult.size(); i++) {
        if (dartResult[i] == 'S') {
        } else if (dartResult[i] == 'D') {
            score[index] = pow(score[index], 2);
        } else if (dartResult[i] == 'T') {
            score[index] = pow(score[index], 3);
        } else if (dartResult[i] == '*') {
            score[index] *= 2;
            if (index > 0) score[index-1] *= 2;
        } else if (dartResult[i] == '#') {
            score[index] *= -1;
        } else {
            index++;
            if (i+1 < dartResult.size() && dartResult[i+1] == '0') {
                score.push_back(10);
                i++;
            } else {
                score.push_back(dartResult[i] - 48);
            }
        }
    }
    for (int i=0; i<score.size(); i++) answer+=score[i];
    return answer;
}

 

반응형
반응형

문제출처

https://programmers.co.kr/learn/courses/30/lessons/17681

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제풀이

2장의 지도를 겹친 값을 얻기 위해 OR 연산을 사용했다. OR연산을 사용하면 문제에서 원하는 전체 지도를 얻을 수 있다. 이후 '#'(벽)과 ' '(공백)을 찾기 위해서는 비트연산을 사용했다. 예를 들어 전체지도의 값이 10진수로 19이라면 2진수로 10011로 나타낼 수 있다. 2진수로 나타낸 값과 1을 오른쪽으로 시프트 한 값(1<<j)의 AND 연산이 1이라면 벽을 추가하고 이외의 경우 공백을 추가하면 된다.

 

비트연산에 대해 이해가 되지 않는다면 아래글을 참조하자.

https://swjeong.tistory.com/114?category=781121

 

[Bitmask] 비트마스크 기초

Bitmask 컴퓨터는 이진번 관련 연산들을 매우 빠르게 진행할 수 있는데, 이러한 특성들을 사용하여 이진수 표현을 자료구조로 사용하는 기법을 비트마스크라고 합니다. 비트마스크는 자료구조라고는 할 수는 없지..

swjeong.tistory.com

 

10011 & 00001 = 1

10011 & 00010 = 1

10011 & 00100 = 0

10011 & 01000 = 0

10011 & 10000 = 1

즉 answer에는 '##  #'의 값이 들어가게 되는데 이는 뒤에서부터 진행한 결과이므로 결과값을 뒤집어 answer 벡터에 추가해주면 된다.

 

 

소스코드

#include <string>
#include <vector>
#include <algorithm>
using namespace std;
vector<string> solution(int n, vector<int> arr1, vector<int> arr2) {
    vector<string> answer;
    for (int i=0; i<n; i++) {
        int sumValue = (arr1[i] | arr2[i]);
        string ans = "";
        for (int j=0; j<n; j++) {
            if (sumValue & (1<<j)) ans+="#";
            else ans+=" ";
        }
        reverse(ans.begin(), ans.end());
        answer.push_back(ans);   
    }
    return answer;
}

 

반응형
반응형

문제출처

https://programmers.co.kr/learn/courses/30/lessons/59045

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제풀이

보호소에 들어올 당시에는 중성화되지 않았지만, 보호소를 나갈때 중성화된 동물'을 찾는 문제이다.

키 값으로 INNER JOIN을 한뒤 ANIMAL_INS에서는 Intact로 시작하고, ANIMAL_OUTS에서는 Spayed나 Neutered로 시작하는 데이터를 찾으면 된다.

 

소스코드

 

SELECT A.ANIMAL_ID
      ,A.ANIMAL_TYPE
      ,A.NAME
FROM   ANIMAL_INS A
      ,ANIMAL_OUTS B
WHERE  A.ANIMAL_ID   = B.ANIMAL_ID
AND    A.ANIMAL_TYPE = B.ANIMAL_TYPE
AND    A.SEX_UPON_INTAKE LIKE 'Intact%'
AND    (B.SEX_UPON_OUTCOME LIKE 'Neutered%' OR B.SEX_UPON_OUTCOME LIKE 'Spayed%')
반응형

'Database' 카테고리의 다른 글

[SQL 튜닝] 2. 옵티마이저(Optimizer)  (0) 2019.04.22
[SQL 튜닝] 1. 실행계획(Execution plan)  (2) 2019.04.22
오라클 다중 WHERE조건  (0) 2018.06.25
무결성 (Integrity)  (0) 2018.01.12
JOIN (조인)  (0) 2018.01.12
반응형

문제출처

https://www.acmicpc.net/problem/16234

 

16234번: 인구 이동

N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모든 나라는 1×1 크기이기 때문에, 모든 국경선은 정사각형 형태이다. 오늘부터 인구 이동이 시작되는 날이다. 인구 이동은 다음과 같이 진행되고, 더 이상 아래 방법에 의해 인구 이동이 없을 때까지 지속된다. 국경선을 공유하는 두 나라의 인구 차이가 L명

www.acmicpc.net

 

문제풀이

BFS로 전체탐색하면 되는 문제이다. 

BFS탐색을 통해 연합국가들을 찾으며 총 인구수와 연합국가 수를 구한다. 연합국가가 있는 경우 값을 문제조건대로 갱신해주고 연합국가가 없는경우 인구이동이 일어난 회수를 출력해주면 된다.

이때 연합국가의 좌표를 vector에 저장해 따로 관리해 주면서 갱신해줬다. 삼성기출문제가 점점 응용력이 필요해지는 것 같다. 문제를 주의깊게 읽고 완벽히 이해한뒤 소스코드를 작성하도록 해야겠다.

 

 

소스코드

https://github.com/sw93/algorithm/blob/master/SW_TEST(samsung)/BOJ_16234/BOJ_16234/boj16234.cpp

 

sw93/algorithm

problem solve. Contribute to sw93/algorithm development by creating an account on GitHub.

github.com

#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
bool flag;
int n, l, r, ans;
int dy[] = { 0, -1, 0, 1 };
int dx[] = { 1, 0, -1, 0 };
int map[50][50];
bool visit[50][50];
vector<pair<int, int> > v;
void init() {
	cin >> n >> l >> r;
	for (int y = 0; y < n; y++) {
		for (int x = 0; x < n; x++) {
			cin >> map[y][x];
		}
	}
}
void bfs(int y, int x) {
	int count = 1, sum = map[y][x];
	queue<pair<int, int> > q;
	q.push(make_pair(y, x));
	v.push_back(make_pair(y, x));
	visit[y][x] = 1;
	
	while (!q.empty()) {
		int y = q.front().first;
		int x = q.front().second;
		q.pop();

		for (int i = 0; i < 4; i++) {
			int ny = y + dy[i];
			int nx = x + dx[i];
			if (ny < 0 || nx < 0 || ny >= n || nx >= n || visit[ny][nx]) continue;

			int diff = abs(map[y][x] - map[ny][nx]);
			if (diff >= l && diff <= r) {
				visit[ny][nx] = 1;
				sum += map[ny][nx];
				count++;
				q.push(make_pair(ny, nx));
				v.push_back(make_pair(ny, nx));
			}
		}
	}

	if (v.size() > 1) {
		flag = 1;
		int updateValue = sum / count;
		for (int i = 0; i < v.size(); i++) map[v[i].first][v[i].second] = updateValue;	
	}
	v.clear();
}
int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);
	init();
	while (true) {
		memset(visit, 0, sizeof(visit));
		flag = 0;
		for (int y = 0; y < n; y++) {
			for (int x = 0; x < n; x++) {
				if (visit[y][x]) continue;
				bfs(y, x);
			}
		}
		if (flag) ans++;
		else break;
	}
	cout << ans << "\n";
	return 0;
}
반응형
반응형

문제출처

https://www.acmicpc.net/problem/17144

 

17144번: 미세먼지 안녕!

미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기의 칸으로 나눴다. 구사과는 뛰어난 코딩 실력을 이용해 각 칸 (r, c)에 있는 미세먼지의 양을 실시간으로 모니터링하는 시스템을 개발했다. (r, c)는 r행 c열을 의미한다. 공기청정기는 항상 1번 열에 설치되어 있고, 크기는 두 행을 차지한다. 공기청정기가 설치되어 있지 않은 칸에는 미세먼

www.acmicpc.net

 

문제풀이

그냥 진짜 구현하는 문제다. 빡구현까지는 아니고 배열 조정을 하느라 약간 머리가 아픈 문제

문제에 나온대로 확산과 공기청정기 순환 2가지로 나눠서 구현하면 된다.

 

spreadDust() 메서드

확산은 tempMap배열을 이용해 구현했다. 확산은 queue를 이용해도 될것같다.

확산과 같은 경우 인접한 공간에 숫자가 있는경우 어떻게 처리하는지가 중요하다. 한 공간(y, x)를 기준으로 인접한 공간에 값이 없다면 그냥 4방향으로 확산시켜주면 되지만, 한 방향이라도 있는 경우 다음 탐색을 할때 영향을 주기 때문이다. 즉, 우리는 순차적으로 한 공간(y, x)에 대해 확산시키는 소스를 구현하지만 문제는 한순간에 확산하기 때문에 영향을 받기전의 값으로 확산을 시켜야 한다.

 

1. map을 tempMap에 복사하여 원래의 미세먼지 값들을 저장.

2. 확산될 먼지의 양은 원본map을 통해 계산

3. tempMap에서 먼지를 확산시킴

4. tempMap에서 확산시킨 것들 다시 map으로 옮김.

 

activateAirCleaner() 메서드

이 부분은 공기청정기를 작동시키는 메서드이다. 기존 입력을 받을때 따로 list에 저장해둔 공기청정기의 y좌표를 이용해 map배열의 값을 옮겨주면 된다. 공기청정기에 들어가는 먼지는 없어진다는 조건을 활용해서 없어지는 좌측부터 하나씩 값을 옮겨주었다. 여기서 주의할 점은 공기청정기가 위치한 y좌표의 x축을 이동시킬때 모두 이동시키고 공기청정기 다음x좌표를 0으로 다시 갱신해줘야 한다는 것이다.

 

소스코드

https://github.com/sw93/algorithm/blob/master/SW_TEST(samsung)/BOJ_17144/boj17144.java

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

public class Main {
    private static int r, c, t;
    private static int dy[] = {0, -1, 0, 1};
    private static int dx[] = {1, 0, -1, 0};
    private static int map[][];
    private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    private static StringTokenizer st;
    private static ArrayList<Integer> cleaner;

    public static void main(String[] args) throws Exception {
        init();
        while (true) {
            t--;
            spreadDust();
            activateAirCleaner();

            if (t == 0) {
                System.out.println(countDustVolumn());
                break;
            }
        }
    }

    private static int countDustVolumn() {
        int ret = 0;
        for (int y=0; y<r; y++) {
            for (int x=0; x<c; x++) {
                if (map[y][x] != 0 && map[y][x] != -1) ret += map[y][x];
            }
        }
        return ret;
    }

    private static void copyMap(int src[][], int dest[][]) {
        for (int y=0; y<r; y++) {
            for (int x=0; x<c; x++) {
                dest[y][x] = src[y][x];
            }
        }
    }

    private static void activateAirCleaner() {
        int upY = cleaner.get(0);
        int downY = cleaner.get(1);

        // 위쪽
        for (int y=upY-1; y>0; y--) {
            map[y][0] = map[y-1][0];
        }
        for (int x=0; x<c-1; x++) {
            map[0][x] = map[0][x+1];
        }
        for (int y=0; y<upY; y++) {
            map[y][c-1] = map[y+1][c-1];
        }
        for (int x=c-1; x>0; x--) {
            map[upY][x] = map[upY][x-1];
        }
        map[upY][1] = 0;

        // 아래쪽
        for (int y=downY+1; y<r-1; y++) {
            map[y][0] = map[y+1][0];
        }
        for (int x=0; x<c-1; x++) {
            map[r-1][x] = map[r-1][x+1];
        }
        for (int y=r-1; y>=downY; y--) {
            map[y][c-1] = map[y-1][c-1];
        }
        for (int x=c-1; x>1; x--) {
            map[downY][x] = map[downY][x-1];
        }
        map[downY][1] = 0;
    }

    private static void spreadDust() {
        int tempMap[][] = new int[r][c];
        copyMap(map, tempMap);

        for (int y=0; y<r; y++) {
            for (int x=0; x<c; x++) {
                if (map[y][x] != 0 && map[y][x] != -1) {
                    int count = 0;
                    int dust = map[y][x] / 5;
                    for (int i=0; i<4; i++) {
                        int ny = y+dy[i];
                        int nx = x+dx[i];

                        if (ny<0 || nx<0 || ny>=r || nx>=c || map[ny][nx] == -1) continue;
                        tempMap[ny][nx] += dust;
                        count++;
                    }
                    tempMap[y][x] -= (count * dust);
                }
            }
        }
        copyMap(tempMap, map);
    }

    private static void init() throws Exception {
        st = new StringTokenizer(br.readLine());
        r = Integer.parseInt(st.nextToken());
        c = Integer.parseInt(st.nextToken());
        t = Integer.parseInt(st.nextToken());
        map = new int[r][c];
        cleaner = new ArrayList<>();

        for (int y=0; y<r; y++) {
            st = new StringTokenizer(br.readLine(), " ");
            for (int x=0; x<c; x++) {
                map[y][x] = Integer.parseInt(st.nextToken());
                if (map[y][x] == -1) cleaner.add(y);
            }
        }
    }
}

 

반응형

'Algorithm' 카테고리의 다른 글

[프로그래머스 17681 - 카카오 2018 1차] 비밀지도  (2) 2020.04.29
[BOJ 16234] 인구 이동  (0) 2020.04.27
[BOJ 14500] 테트노미로  (0) 2020.04.24
[BOJ 10819] 차이를 최대로  (0) 2020.04.21
[BOJ 16236] 아기상어  (0) 2020.04.21
반응형

문제출처

https://www.acmicpc.net/problem/14500

 

14500번: 테트로미노

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. 정사각형은 서로 겹치면 안 된다. 도형은 모두 연결되어 있어야 한다. 정사각형의 변끼리 연결되어 있어야 한다. 즉, 꼭짓점과 꼭짓점만 맞닿아 있으면 안 된다. 정사각형 4개를 이어 붙인 폴리오미노는 테트로미노라고 하며, 다음과 같은 5가지가 있다. 아름이는 크기가 N×M인 종이 위에 테트로미노 하나를 놓으려고 한다. 종이는 1×1 크기의 칸으로 나누

www.acmicpc.net

 

문제풀이

N x M 배열에 테트리스 도형들을 적절히 회전하여 1개를 놓았을때 놓인 칸들의 최대 합을 구하는 문제입니다.

삼성 기출문제답게 map위에서 동,북,서,남 방향으로 탐색해서 풀이하면 될것이라 생각했지만 'ㅜ'모양은 기존 dfs와 다른 방식으로 탐색해야했습니다.

'ㅜ' 모양을 탐색하는 제 아이디어는 다음과 같습니다.

 

1. 해당 위치를 기준으로 동,북,서,남 방향 모두 탐색하며 map에 저장된 값들을 더한다.

2. 탐색 시 매번 map의 최소값을 구한다.

3. 모두 탐색한 뒤 최소값을 빼준다.

즉, 현재위치 + 4방향 - 4방향중 최소값으로 'ㅜ'모양을 탐색했습니다.

+ 모양으로 탐색한 뒤 가장 최소값을 빼주면 'ㅜ'의 회전체 모양이 나오기 때문입니다.

 

소스코드

https://github.com/sw93/algorithm/blob/master/SW_TEST(samsung)/BOJ_14500/boj14500.java

 

sw93/algorithm

problem solve. Contribute to sw93/algorithm development by creating an account on GitHub.

github.com

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

public class Main {
    private static int n, m, ans=0;
    private static int dy[] = {0, -1, 0, 1};
    private static int dx[] = {1, 0, -1, 0};
    private static int map[][];
    private static boolean visit[][];

    public static void main(String[] args) throws Exception {
        init();
        for (int y=0; y<n; y++) {
            for (int x=0; x<m; x++) {
                dfs(y, x, 0, 0);
                checkException(y, x);
            }
        }
        System.out.println(ans);
    }

    private static void dfs(int y, int x, int sum, int count) {
        if (count == 4) {
            ans = Math.max(ans, sum);
            return;
        }

        for (int i=0; i<4; i++) {
            int ny = y+dy[i];
            int nx = x+dx[i];
            if (ny<0 || nx<0 || ny>=n || nx>=m || visit[ny][nx]) continue;
            visit[ny][nx] = true;
            dfs(ny, nx, sum+map[ny][nx], count+1);
            visit[ny][nx] = false;
        }
    }

    private static void checkException(int y, int x) {
        int sum = map[y][x];
        int count = 1;
        int min = 987654321;

        for (int i=0; i<4; i++) {
            int ny = y+dy[i];
            int nx = x+dx[i];
            if (ny<0 || nx<0 || ny>=n || nx>=m) continue;
            sum += map[ny][nx];
            min = Math.min(min, map[ny][nx]);
            count++;
        }

        if (count == 5) {
            sum -= min;
        }
        ans = Math.max(ans, sum);
    }

    private static void init() throws Exception {
        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];
        visit = new boolean[n][m];

        for (int y = 0; y < n; y++) {
            st = new StringTokenizer(br.readLine());
            for (int x = 0; x < m; x++) {
                map[y][x] = Integer.parseInt(st.nextToken());
            }
        }
    }
}
반응형

'Algorithm' 카테고리의 다른 글

[BOJ 16234] 인구 이동  (0) 2020.04.27
[BOJ 17144] 미세먼지 안녕!  (0) 2020.04.24
[BOJ 10819] 차이를 최대로  (0) 2020.04.21
[BOJ 16236] 아기상어  (0) 2020.04.21
[BOJ 15683] 감시  (0) 2020.04.20
반응형

문제 출처

https://www.acmicpc.net/problem/10819

 

10819번: 차이를 최대로

첫째 줄에 N (3 ≤ N ≤ 8)이 주어진다. 둘째 줄에는 배열 A에 들어있는 정수가 주어진다. 배열에 들어있는 정수는 -100보다 크거나 같고, 100보다 작거나 같다.

www.acmicpc.net

 

문제 풀이

next_permutation을 사용해 다음 순열을 구하고 차이값을 계속 갱신해서 최대값을 구한다.

 

소스코드

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int calc(vector<int>& v) {
    int sum = 0;
    for (int i = 1; i < v.size(); i++) {
        sum += abs(v[i] - v[i - 1]);
    }
    return sum;
}
int main() {
    ios_base::sync_with_stdio(0); cin.tie(0);
    int n;
    cin >> n;
    vector<int> v(n);
    for (int i = 0; i < n; i++) cin >> v[i];
    sort(v.begin(), v.end());
    int ans = 0;
    do {
        int tmp = calc(v);
        ans = max(ans, tmp);
    } while (next_permutation(v.begin(), v.end()));
    cout << ans << "\n";
    return 0;
}
반응형

'Algorithm' 카테고리의 다른 글

[BOJ 17144] 미세먼지 안녕!  (0) 2020.04.24
[BOJ 14500] 테트노미로  (0) 2020.04.24
[BOJ 16236] 아기상어  (0) 2020.04.21
[BOJ 15683] 감시  (0) 2020.04.20
[BOJ 17140] 이차원 배열과 연산  (0) 2020.04.17
반응형

문제출처

https://www.acmicpc.net/problem/16236

 

문제풀이

BFS로 풀이했다. 일반적인 BFS와 다르게 먹이를 찾으면 더이상 탐색을 하지 않는게 포인트였다. 처음 입력을 받을때 아기상어의 위치를 구조체에 저장하고 map에는 0으로 저장해 조건탐색을 쉽게 할 수 있었다.

이 문제도 na982님 강의를 보고 구현했다. 점점 난이도가 올라가는데 혼자 풀수있도록 구현방법들을 잘 익혀둬야겠다.

 

소스코드

#include <iostream>
#include <queue>
using namespace std;
struct SHARK {
	int y, x, time;
};
SHARK shark;
int n, sharkSize, eatCount;
const int dy[] = { -1, 1, 0, 0 };
const int dx[] = { 0, 0, -1, 1 };
int map[20][20];
void init() {
	cin >> n;
	for (int y = 0; y < n; y++) {
		for (int x = 0; x < n; x++) {
			cin >> map[y][x];
			if (map[y][x] == 9) {
				shark.y = y, shark.x = x, shark.time = 0;
				sharkSize = 2, eatCount = 0;
				map[y][x] = 0;
			}
		}
	}
}
void bfs() {
	bool existFood = 1;
	while (existFood) {
		existFood = 0;
		bool visit[20][20] = { 0 };
		queue<SHARK> q;
		q.push(shark);
		visit[shark.y][shark.x] = 1;

		SHARK nextFood;	// 다음 먹이 정보
		nextFood.y = 20;
		nextFood.time = -1;
		while (!q.empty()) {

			// 탐색 현재 위치
			SHARK cur = q.front();
			q.pop();
			
			// 먹이를 찾은경우
			if (map[cur.y][cur.x] != 0 && map[cur.y][cur.x] < sharkSize) {
				existFood = 1;

				// 새로 찾은 먹이의 좌표가 위쪽이거나 왼쪽에 있는경우
				if (cur.y < nextFood.y || (cur.y == nextFood.y && cur.x < nextFood.x)) {
					nextFood = cur;
				}
			}

			// 다음 먹이의 위치를 찾은 경우 탐색 중단
			if (nextFood.time != -1 && cur.time > nextFood.time) break;

			// 4방향 탐색
			for (int i = 0; i < 4; i++) {
				int ny = cur.y + dy[i];
				int nx = cur.x + dx[i];
				int time = cur.time + 1;
				if (ny < 0 || nx < 0 || ny >= n || nx >= n || visit[ny][nx]) continue;
				if (map[ny][nx] > sharkSize) continue;
				visit[ny][nx] = 1;
				q.push({ ny,nx, time });
			}
		}

		// 탐색 종료후 먹이를 찾은경우
		if (existFood) {
			eatCount++;
			shark = nextFood;
			if (sharkSize == eatCount) {
				sharkSize++;
				eatCount = 0;
			}
			map[shark.y][shark.x] = 0;
		}
	}
}
int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);
	init();
	bfs();
	cout << shark.time;
	return 0;
}
반응형

'Algorithm' 카테고리의 다른 글

[BOJ 14500] 테트노미로  (0) 2020.04.24
[BOJ 10819] 차이를 최대로  (0) 2020.04.21
[BOJ 15683] 감시  (0) 2020.04.20
[BOJ 17140] 이차원 배열과 연산  (0) 2020.04.17
[BOJ 15685] 드래곤 커브  (0) 2020.04.13
반응형

문제출처

https://www.acmicpc.net/problem/15683

 

문제풀이

8대의 카메라가 4방향 모두 탐색하는 경우가 총 64개의 공간에서 일어날 수 있으므로 이 문제의 시간복잡도는 대략 4^8*64이므로 완전탐색으로 1초안에 풀이 가능하다.

입력을 받을때 cctv의 타입과 좌표를 따로 저장하고 dfs로 완전탐색해서 풀이했다. 처음에 어떻게 탐색을 해야하는지 고생을 했는데 1시간동안 탐색방법이 떠오르지 않아 na982님의 풀이를 확인하고 문제풀이를 했다. 그러다보니 na982님 풀이에 생각이 박혀서 다시 풀어도 같은 소스코드가 나왔다. 이 풀이에서 4방향 탐색을 할때 하나의 함수를 만들어 안에서 분기처리 하는 방법이 매우 마음에 들었다. 비록 이 문제는 내가 처음부터 끝까지 풀지는 못했으나 좋은 아이디어를 얻는 계기가 된듯 하다.

풀이방법은 https://na982.tistory.com/95 여기를 참조하자. 정말 잘 설명해주시는듯 ㅠㅠ

 

소스코드

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct CCTV {
	int type, y, x;
};
int n, m, ans = 987654321;
const int rotateCount[] = { 4,2,4,4,1 };
int map[8][8];
vector<CCTV> cctv;
void init() {
	cin >> n >> m;
	for (int y = 0; y < n; y++) {
		for (int x = 0; x < m; x++) {
			cin >> map[y][x];
			if (map[y][x] != 0 && map[y][x] != 6) {
				cctv.push_back({ map[y][x], y, x });
			}
		}
	}
}
void copyMap(int src[8][8], int desc[8][8]) {
	for (int y = 0; y < n; y++) {
		for (int x = 0; x < m; x++) {
			desc[y][x] = src[y][x];
		}
	}
}
void rotateCamera(int dir, CCTV cctv) {
	dir %= 4;

	if (dir == 0) {
		for (int x = cctv.x + 1; x < m; x++) {
			if (map[cctv.y][x] == 6) break;
			map[cctv.y][x] = -1;
		}
	} else if (dir == 1) {
		for (int y = cctv.y - 1; y >= 0; y--) {
			if (map[y][cctv.x] == 6) break;
			map[y][cctv.x] = -1;
		}
	} else if (dir == 2) {
		for (int x = cctv.x - 1; x >= 0; x--) {
			if (map[cctv.y][x] == 6) break;
			map[cctv.y][x] = -1;
		}
	} else if (dir == 3) {
		for (int y = cctv.y + 1; y < n; y++) {
			if (map[y][cctv.x] == 6) break;
			map[y][cctv.x] = -1;
		}
	}
}
void dfs(int index) {
	if (index == cctv.size()) {
		int safeArea = 0;
		for (int y = 0; y < n; y++) {
			for (int x = 0; x < m; x++) {
				if (map[y][x] == 0) safeArea++;
			}
		}
		ans = min(ans, safeArea);
		return;
	}
	int type = cctv[index].type;
	int backup[8][8] = { 0, };
	for (int i = 0; i < rotateCount[type-1]; i++) {
		copyMap(map, backup);
		if (type == 1) {
			rotateCamera(i, cctv[index]);
		} else if (type == 2) {
			rotateCamera(i, cctv[index]);
			rotateCamera(i + 2, cctv[index]);
		} else if (type == 3) {
			rotateCamera(i, cctv[index]);
			rotateCamera(i + 1, cctv[index]);
		} else if (type == 4) {
			rotateCamera(i, cctv[index]);
			rotateCamera(i + 1, cctv[index]);
			rotateCamera(i + 2, cctv[index]);
		} else if (type == 5) {
			rotateCamera(i, cctv[index]);
			rotateCamera(i + 1, cctv[index]);
			rotateCamera(i + 2, cctv[index]);
			rotateCamera(i + 3, cctv[index]);
		}
		dfs(index + 1);
		copyMap(backup, map);
	}

}
int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);
	init();
	dfs(0);
	cout << ans << "\n";
	return 0;
}
반응형

'Algorithm' 카테고리의 다른 글

[BOJ 10819] 차이를 최대로  (0) 2020.04.21
[BOJ 16236] 아기상어  (0) 2020.04.21
[BOJ 17140] 이차원 배열과 연산  (0) 2020.04.17
[BOJ 15685] 드래곤 커브  (0) 2020.04.13
[BOJ 17142] 연구소3  (0) 2020.04.12

+ Recent posts