[문제 링크]

 

1051번: 숫자 정사각형

N*M크기의 직사각형이 있다. 각 칸은 한 자리 숫자가 적혀 있다. 이 직사각형에서 꼭짓점에 쓰여 있는 수가 모두 같은 가장 큰 정사각형을 찾는 프로그램을 작성하시오. 이때, 정사각형은 행 또는 열에 평행해야 한다.

www.acmicpc.net


깊게 생각하지 않고 단순하게 접근하면 쉽게 풀리는 문제라 생각한다.

map[0][0]을 기준으로 검사할 때를 예로 들어보자면 map[0][0], map[0+k][0], map[0][0+k] 세 값이 일치할 때

즉, 세 꼭짓점의 숫자가 같다면 마지막 꼭짓점인 map[0+k][0+k]과 map[0][0] 값이 일치하는지 검사한다.

일치한다면 조건을 만족하는 정사각형이 되므로 k는 정사각형 한 변의 길이가 된다.

문제 예제에서 k = 2일 때 정사각형 넓이가 9로 출력되었으니 정사각형의 넓이는 (k+1)^2라는 것을 알 수 있다.

따라서 map[0][0] ~ map[n-1][n-1] 까지 모든 원소를 다 탐색하면서 조건을 만족하는 정사각형이 만들어질 때 그 넓이가 가장 큰 값을 갱신해주면 원하는 결과를 얻을 수 있다.


#include <iostream>
#include <vector>
#include <string>
using namespace std;
 
vector<string> board;
int colMax, rowMax;
int MaxSquare = 1;
int max(int a, int b) { return a > b ? a : b; }
void Solution()
{
    for (int i = 0; i < colMax; i++)
        for (int j = 0; j < rowMax; j++)
            for (int k = 1; k < colMax; k++)
                if (i + k < colMax && j + k < rowMax)
                    if (board[i][j] == board[i + k][j] && board[i][j] == board[i][j + k])
                        if (board[i][j] == board[i + k][j + k])
                            MaxSquare = max(MaxSquare, (k+1)*(k+1));
}
int main(void)
{
    cin >> colMax >> rowMax;
    for (int i = 0; i < colMax; i++)
    {
        string str;
        cin >> str;
        board.push_back(str);
    }
    Solution();
    cout << MaxSquare << endl;
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

알고리즘 200일 프로젝트 - 19day

내일도 열심히!

[문제 링크]

 

3085번: 사탕 게임

문제 상근이는 어렸을 적에 "봄보니 (Bomboni)" 게임을 즐겨했다. 가장 처음에 N×N크기에 사탕을 채워 놓는다. 사탕의 색은 모두 같지 않을 수도 있다. 상근이는 사탕의 색이 다른 인접한 두 칸을 고른다. 그 다음 고른 칸에 들어있는 사탕을 서로 교환한다. 이제, 모두 같은 색으로 이루어져 있는 가장 긴 연속 부분(행 또는 열)을 고른 다음 그 사탕을 모두 먹는다. 사탕이 채워진 상태가 주어졌을 때, 상근이가 먹을 수 있는 사탕의 최대 개수를 구하

www.acmicpc.net


바꾸지 않은 상태에서 먹을 수 있는 최대 사탕갯수를 먼저 구한 다음, 보드의 0,0좌표를 시작으로 스왑하는 모든 경우의 수에 대하여 최댓값을 갱신해주면 된다.

왼쪽위에서부터 차례대로 스왑을 진행하기 때문에 한 칸에서 상하좌우 모든 방향으로 스왑하는 경우를 계산할 필요 없이 왼쪽과 아랫쪽 사탕과 스왑하는 경우만 계산해줘도 모든 경우를 확인할 수 있다.

추가로 구한 사탕 개수가 보드의 행 길이와 같다면 그 값보다 큰 값이 나올 수 없으므로 함수를 리턴하는 조건을 달아주었다.


#include <iostream>
#include <string>
#include <vector>
using namespace std;
 
vector<string> board;
int maxLen, candyMax = 1;
 
inline int max(int a, int b) { return a > b ? a : b; }
 
void FindCandyMax()
{
    for (int i = 0; i < maxLen; i++)
    {
        for (int j = 0; j < maxLen; j++)
        {
            int temp = j, colCandyCnt = 1, rowCandyCnt = 1;
            bool colCandy = true, rowCandy = true;
            while (++temp < maxLen)
            {
                if (colCandy && board[j][i] != board[temp][i])
                    colCandy = false;
                if (rowCandy && board[i][j] != board[i][temp])
                    rowCandy = false;
                if (!colCandy && !rowCandy) break;
                if (colCandy) colCandyCnt++;
                if (rowCandy) rowCandyCnt++;
            }
            candyMax = max(candyMax, max(colCandyCnt, rowCandyCnt));
        }
    }
}
 
void CandySwap(int col, int row)
{
    char temp = board[col][row];
    if (row + 1 < maxLen)
    {
        board[col][row] = board[col][row + 1];
        board[col][row + 1= temp;
        FindCandyMax();
        board[col][row + 1= board[col][row];
        board[col][row] = temp;
    }
    if (col + 1 < maxLen)
    {
        board[col][row] = board[col + 1][row];
        board[col + 1][row] = temp;
        FindCandyMax();
        board[col + 1][row] = board[col][row];
        board[col][row] = temp;
    }
}
 
void Solution()
{
    FindCandyMax();
    if (candyMax == maxLen) return;
    for(int i=0; i<maxLen; i++)
        for (int j = 0; j < maxLen; j++)
        {
            CandySwap(i, j);
            if (candyMax == maxLen) return;
        }
}
 
int main(void)
{
    cin >> maxLen;
    for(int i=0; i<maxLen; i++)
    {
        string str;
        cin >> str;
        board.push_back(str);
    }
    Solution();
    cout << candyMax << endl;
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

알고리즘 200일 프로젝트 - 19day

내일도 열심히!

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

백준 1038번: 감소하는 수  (0) 2020.04.25
백준 1051번 : 숫자 정사각형  (0) 2020.04.24
백준 2503번: 숫자 야구 (c++)  (0) 2020.04.23
백준 15684번: 사다리 조작 (c++)  (0) 2020.04.22
백준 10448: 유레카 이론 (c++)  (0) 2020.04.21

[문제 링크]

 

2503번: 숫자 야구

첫째 줄에는 민혁이가 영수에게 몇 번이나 질문을 했는지를 나타내는 1 이상 100 이하의 자연수 N이 주어진다. 이어지는 N개의 줄에는 각 줄마다 민혁이가 질문한 세 자리 수와 영수가 답한 스트라이크 개수를 나타내는 정수와 볼의 개수를 나타내는 정수, 이렇게 총 세 개의 정수가 빈칸을 사이에 두고 주어진다.

www.acmicpc.net


솔루션만 생각해낸다면 어렵지 않게 구현할 수 있다.

필자는 민혁이가 질문한 숫자와 그 숫자에 대한 스트라이크, 볼 갯수를 vector배열에 저장한 다음 1~9까지 숫자로 세 자리 숫자를 만들 수 있는 모든 경우의 수(숫자 중복 제외)에 대하여 질문한 숫자와 비교해 스트라이크, 볼 갯수가 모두 일치한다면 카운트를 1증가 시키는 식으로 구현하였다.


 
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<pair<stringpair<intint>>> answer;
 
int Solution()
{
    int cnt = 0;
    int strike, ball;
    bool check;
    for(int i=1; i<10; i++)
        for (int j = 1; j < 10; j++)
        {
            if (j == i) continue;
            for (int k = 1; k < 10; k++)
            {
                if (k == i || k == j) continue;
                check = true;
                for (vector<pair<stringpair<intint>>>::size_type l = 0; l < answer.size(); l++)
                {
                    strike = ball = 0;
                    for (int m = 0; m < 3; m++)
                    {
                        int number = answer[l].first[m] - '0';
                        if (i == number || j == number || k == number)
                        {
                            if (i == number && m == 0) strike++;
                            else if (j == number && m == 1) strike++;
                            else if (k == number && m == 2) strike++;
                            else ball++;
                        }
                    }
                    if (answer[l].second.first != strike || answer[l].second.second != ball)
                    {
                        check = false;
                        break;
                    }
                    if (strike == 3return 1;
                }
                if (check)
                    cnt++;
            }
        }
    return cnt;
}
int main(void)
{
    int ans;
    cin >> ans;
    while (ans--)
    {
        string number;
        int strike, ball;
        cin >> number >> strike >> ball;
        answer.push_back(make_pair(number, make_pair(strike, ball)));
    }
    cout << Solution() << endl;
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

알고리즘 200일 프로젝트 - 18day

내일도 열심히!

[문제 링크]

 

15684번: 사다리 조작

사다리 게임은 N개의 세로선과 M개의 가로선으로 이루어져 있다. 인접한 세로선 사이에는 가로선을 놓을 수 있는데, 각각의 세로선마다 가로선을 놓을 수 있는 위치의 개수는 H이고, 모든 세로선이 같은 위치를 갖는다. 아래 그림은 N = 5, H = 6 인 경우의 그림이고, 가로선은 없다. 초록선은 세로선을 나타내고, 초록선과 점선이 교차하는 점은 가로선을 놓을 수 있는 점이다. 가로선은 인접한 두 세로선을 연결해야 한다. 단, 두 가로선이 연속하거나 서로

www.acmicpc.net


생각해야 될 것이 두가지 정도 있다고 생각한다.

1. 현재 위치에서 사다리가 연결되어있는지 안되어있는지 어떻게 확인할 것인가?

--> 사다리의 bool형 2차원 배열을 만들어 false로 초기화하고 연결된 지점을 true로 설정함

2. 현재 위치가 연결된 지점(true)이라면 왼쪽으로 갈 것인가? 오른쪽으로 갈 것인가?

--> 이 부분에서 오래 고민했다. A >>> B 방향으로 가는 사다리가 있을 때 A지점만 true로 설정해준다음 사다리를 타는 함수에서는 (현재 row좌표 - 1) 좌표가 true인지 확인하고 true라면 왼쪽으로 이동, true가 아니고 현재 지점이 true라면 오른쪽으로 이동하도록 구현하였다.

 

이정도만 주의해서 구현 시킨다면 무난히 해결할 수 있을 것이다. 연결이 안된부분에 사다리를 1개~3개까지 놓는 모든 경우의 수에 대하여 사다리가 1:1매칭이 되는지 안되는지 확인하고 가장 적은 갯수를 반환해주면 원하는 결과를 얻을 수 있다.


#include <iostream>
#include <cstring>
using namespace std;
 
const int INF = 987654321;
bool ladder[31][11];
int col, row;
inline int min(int a, int b) { return a < b ? a : b; }
bool SuccessCheck()    // 사다리가 1:1 매치가되는지 확인
{
    for (int i = 1; i <= row; i++)
    {
        int start = i; // 시작할 위치(row) 저장
        for (int j = 1; j <= col; j++)
        {
            if (ladder[j][start - 1])
                start--;
            else if (ladder[j][start])
                start++;
        }
        if (start != i) return false;
    }
    return true;
}
int Solution(int startY, int startX, int pick)
{
    if (SuccessCheck()) return pick; // 기저사례. 사다리가 1:1매칭된다면 pick값 반환
    if (pick == 3return INF; // 기저사례. 사다리 3개 추가했는데 위에 기저사례를 통과 못했으므로 무조건 불가능함
    int ret = INF;
    for (int i = startY; i <= col; i++)
        for (int j = 1; j <= row; j++)
        {
            if (startY == i && startX > j) continue// 중복탐색 제거
            if (!ladder[i][j] && !ladder[i][j - 1&& !ladder[i][j + 1]) // 탐색지점 좌우측에 이미 사다리가 연결되었다면 사다리 생성 불가
            {
                ladder[i][j] = true;
                ret = min(ret, Solution(i, j, pick + 1));
                ladder[i][j] = false;
            }
        }
    return ret;
}
int main(void)
{
    int ldNum;
    cin >> row >> ldNum >> col;
    memset(ladder, falsesizeof(ladder));
    while (ldNum--)
    {
        int c, r;
        cin >> c >> r;
        ladder[c][r] = true;
    }
    int result = Solution(000);
    if (result == INF)
        cout << -1 << endl;
    else
        cout << result << endl;
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

알고리즘 200일 프로젝트 - 17day

내일도 열심히!

[문제 링크]

 

10448번: 유레카 이론

문제 삼각수 Tn(n ≥ 1)는 [그림]에서와 같이 기하학적으로 일정한 모양의 규칙을 갖는 점들의 모음으로 표현될 수 있다. [그림] 자연수 n에 대해 n ≥ 1의 삼각수Tn는 명백한 공식이 있다. Tn = 1 + 2 + 3 + ... + n = n(n+1)/2 1796년, 가우스는 모든 자연수가 최대 3개의 삼각수의 합으로 표현될 수 있다고 증명하였다. 예를 들어, 4 = T1 + T2 5 = T1 + T1 + T2 6 = T2 + T2 or 6 = T

www.acmicpc.net


3중 for문을 사용하면 쉽고 간편하게 구현할 수 있는 문제였다. 하지만 나는 3중 for문을 생각못하고 재귀호출로 구현해서 코드가 길어지고 복잡해진거 같다.


#include <iostream>
using namespace std;
 
int num;
bool eureka;
void Solution(int start, int sum, int pick)
{
    if (pick == 3 && num == sum)
    {
        eureka = true;
        return;
    }
    else if (pick >= 3 || sum > num) return;
 
    int triNum;
    for (int n = start; n < 50; n++)
    {
        triNum = (n * (n + 1)) / 2;
        Solution(n + 1, sum + triNum, pick + 1);
        Solution(n + 1, sum + (triNum * 2), pick + 2);
        Solution(n + 1, sum + (triNum * 3), pick + 3);
    }
}
int main(void)
{
    int testcase;
    cin >> testcase;
    while (testcase--)
    {
        cin >> num;
        eureka = false;
        Solution(1,0,0);
        cout << eureka << endl;
    }
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

알고리즘 200일 프로젝트 - 16day

내일도 열심히!

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

백준 2503번: 숫자 야구 (c++)  (0) 2020.04.23
백준 15684번: 사다리 조작 (c++)  (0) 2020.04.22
백준 1748번: 수 이어 쓰기 1 (C++)  (0) 2020.04.20
백준 12100번: 2048(Easy) (C++)  (0) 2020.04.19
백준 15683번: 감시 (C++)  (0) 2020.04.18

[문제 링크]

 

1748번: 수 이어 쓰기 1

첫째 줄에 N(1≤N≤100,000,000)이 주어진다.

www.acmicpc.net


i = 1부터 N까지 반복할때마다 i의 자릿수를 sum변수에 더해주면 원하는 결과를 얻을 수 있다.


#include <iostream>
#include <cmath>
using namespace std;
 
int main(void)
{
    int num;
    cin >> num;
    int temp = num, digit = 1;
    while ((temp / 10!= 0
        temp /= 10, digit++;
 
    int i=1, sum = 0, digitNum = 1,digitMax = 10;
    while (digit--)
    {
        for ( ; i < digitMax; i++)
        {
            if (i > num)
            {
                cout << sum << endl;
                return 0;
            }
            else
            {
                sum += digitNum;
            }
        }
        digitNum++;
        digitMax *= 10;
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

알고리즘 200일 프로젝트 - 15day

내일도 열심히!

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

백준 15684번: 사다리 조작 (c++)  (0) 2020.04.22
백준 10448: 유레카 이론 (c++)  (0) 2020.04.21
백준 12100번: 2048(Easy) (C++)  (0) 2020.04.19
백준 15683번: 감시 (C++)  (0) 2020.04.18
백준 1065번: 한수  (0) 2020.04.17

[문제 링크]

 

12100번: 2048 (Easy)

첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2보다 크거나 같고, 1024보다 작거나 같은 2의 제곱꼴이다. 블록은 적어도 하나 주어진다.

www.acmicpc.net


이것저것 생각할 게 많아서 재미있는 문제였다.

알고리즘은 다음과 같다.

한번 움직이는데 가능한 경우의 수는 위 아래 왼쪽 오른쪽 4개의 경우가 있으며 최대 5번 움직이기 때문에 움직일 수 있는 모든 경우의 수를 다해보고, 움직인 횟수가 5번이 됐을 때를 기저사례로 추가하여 보드의 최댓값을 변수에 저장해주면 된다.

같은 숫자일때 합쳐지는 것과 움직이는 방향에 따라 합쳐지는 우선순위가 다르다는 점을 구현하기 위해 Queue를 사용하였다.

 

위로 올리는 경우를 예로 들면,

1. 동일한 x좌표 상에서 y좌표만 0부터 N-1까지 차례대로 큐에 넣는다.

2. 큐의 첫번째 원소를 first, 두번째 원소를 second에 저장하고 저장한 원소는 제거한다.

if (0은 빈 칸을 뜻하므로 first또는 second에 0이 저장되있다면 다시 2번 과정을 반복한다.)

if (큐가 비어있는지 확인하고 비어있다면 위 과정은 건너뛴다.)

3. first와 second가 같은 숫자라면 first * 2한 값을 board[0][x]에 넣어주고, first = 0, second = 0 으로 바꿔준다.

다른 숫자라면 first를 board[0][x]에 넣어주고 first = second, second = 0 으로 바꿔준다.

4. y좌표가 N-1이 될 때까지 y를 1 증가시키면서 2, 3번 과정을 반복한다.

5. x좌표가 N-1이 될 때까지 x를 1증가시키면서 1번~4번 과정을 반복한다.

 

위의 과정을 위, 아래, 왼쪽, 오른쪽의 경우에 대해 각각 다르게 구현해준 다음, 모든 경우의 수를 완전탐색하면 원하는 결과를 얻을 수 있다.


지금 보여드리는 코드는 중복되는 코드를 최대한 줄여놓은 코드입니다.

이해하기 힘드신분들을 위해 줄이기 전 코드도 함께 첨부해드릴게요.

더보기
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
 
int board[21][21];
int maxLen;
int maxNum = -987654321;
int max(int a, int b) { return a > b ? a : b; }
void Solution(int moveCnt);    // 전방선언
void AddBoard(queue<int>& tempQ, int here, int type)
{
    int fir = 0, sec = 0;
    for (int i = 0; i < maxLen; i++)
    {
        while (!tempQ.empty())
        {
            int n = tempQ.front();
            tempQ.pop();
            if (fir == 0) fir = n;
            else if (sec == 0) sec = n;
            if (fir != 0 && sec != 0break;
        }
        switch (type)
        {
        case 0:    // 위로 올렸을 때
            if (fir == sec)
            {
                board[i][here] = fir * 2;
                fir = 0, sec = 0;
            }
            else
            {
                board[i][here] = fir;
                fir = sec, sec = 0;
            }
            break;
        case 1:    // 아래로 내렸을 때
            if (fir == sec)
            {
                board[maxLen - 1 - i][here] = fir * 2;
                fir = 0, sec = 0;
            }
            else
            {
                board[maxLen - 1 - i][here] = fir;
                fir = sec, sec = 0;
            }
            break;
        case 2:    // 오른쪽으로 밀었을 때
            if (fir == sec)
            {
                board[here][i] = fir * 2;
                fir = 0, sec = 0;
            }
            else
            {
                board[here][i] = fir;
                fir = sec, sec = 0;
            }
            break;
        case 3:    // 왼쪽으로 밀었을 때
            if (fir == sec)
            {
                board[here][maxLen - 1 - i] = fir * 2;
                fir = 0, sec = 0;
            }
            else
            {
                board[here][maxLen - 1 - i] = fir;
                fir = sec, sec = 0;
            }
 
        }
    }
}
void MovingBoard(int type, int moveCnt)
{
    queue<int> tempQ;
    switch (type)
    {
    case 0:    // 위로 올렸을 때
        for (int i = 0; i < maxLen; i++)
        {
            for (int j = 0; j < maxLen; j++)
                tempQ.push(board[j][i]);
            AddBoard(tempQ, i, type);
        }
        Solution(moveCnt + 1);
        break;
    case 1:    // 아래로 내렸을 때
        for (int i = 0; i < maxLen; i++)
        {
            for (int j = maxLen - 1; j >= 0; j--)
                tempQ.push(board[j][i]);
            AddBoard(tempQ, i, type);
        }
        Solution(moveCnt + 1);
        break;
    case 2// 오른쪽으로 밀었을 때
        for (int i = 0; i < maxLen; i++)
        {
            for (int j = 0; j < maxLen; j++)
                tempQ.push(board[i][j]);
            AddBoard(tempQ, i, type);
        }
        Solution(moveCnt + 1);
        break;
    case 3:    // 왼쪽으로 밀었을 때
        for (int i = 0; i < maxLen; i++)
        {
            for (int j = maxLen - 1; j >= 0; j--)
                tempQ.push(board[i][j]);
            AddBoard(tempQ, i, type);
        }
        Solution(moveCnt + 1);
        break;
    }
}
void Solution(int moveCnt)
{
    if (moveCnt == 5)
    {
        for (int i = 0; i < maxLen; i++)
            for (int j = 0; j < maxLen; j++)
                maxNum = max(maxNum, board[i][j]);
        return;
    }
 
    int temp[21][21];
    memcpy(temp, board, sizeof(board));
    int type = 4;
    while (type--)    // 4번 반복(상하좌우)
    {
        MovingBoard(type, moveCnt);
        memcpy(board, temp, sizeof(board));
    }
}
int main(void)
{
    cin >> maxLen;
    int n;
    for (int i = 0; i < maxLen; i++)
        for (int j = 0; j < maxLen; j++)
            cin >> board[i][j];
    Solution(0);
    cout << maxNum << endl;
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
 
int board[21][21];
int maxLen;
int maxNum = -987654321;
int max(int a, int b) { return a > b ? a : b; }
void Solution(int moveCnt);    // 전방선언
void AddNumber(int& fir, int& sec, int col, int row)
{
    if (fir == sec)
    {
        board[col][row] = fir * 2;
        fir = 0, sec = 0;
    }
    else
    {
        board[col][row] = fir;
        fir = sec, sec = 0;
    }
}
void AddBoard(queue<int>& tempQ, int here, int type)
{
    int fir = 0, sec = 0;
    for (int i = 0; i < maxLen; i++)
    {
        while (!tempQ.empty())
        {
            int n = tempQ.front();
            tempQ.pop();
            if (fir == 0) fir = n;
            else if (sec == 0) sec = n;
            if (fir != 0 && sec != 0break;
        }
        switch (type)
        {
        case 0:    // 위로 올렸을 때
            AddNumber(fir, sec, i, here);
            break;
        case 1:    // 아래로 내렸을 때
            AddNumber(fir, sec, maxLen - 1 - i, here);
            break;
        case 2:    // 오른쪽으로 밀었을 때
            AddNumber(fir, sec, here, i);
            break;
        case 3:    // 왼쪽으로 밀었을 때
            AddNumber(fir, sec, here, maxLen - 1 - i);
            break;
        }
    }
}
void Moving(int start, int endint type, int moveCnt)
{
    queue<int> tempQ;
    for (int i = 0; i < maxLen; i++)
    {
        if (type == 0 || type == 2)    // 위로 올렸을 때 || 오른쪽으로 밀었을 때
            for (int j = start; j < end; j++)
            {
                if (type == 0
                    tempQ.push(board[j][i]);
                else 
                    tempQ.push(board[i][j]);
            }
        else // 아래로 내렸을 때 || 왼쪽으로 밀었을 때
            for (int j = start; j >= end; j--)
            {
                if (type == 1
                    tempQ.push(board[j][i]);
                else 
                    tempQ.push(board[i][j]);
            }
        AddBoard(tempQ, i, type);
    }
    Solution(moveCnt + 1);
}
void MovingBoard(int type, int moveCnt)
{
    if (type == 0 || type == 2)
        Moving(0, maxLen, type, moveCnt);
    else
        Moving(maxLen - 10, type, moveCnt);
}
void Solution(int moveCnt)
{
    if (moveCnt == 5)    // 기저사례. 5번 이동했다면 보드에서 제일 큰 수 저장
    {
        for (int i = 0; i < maxLen; i++)
            for (int j = 0; j < maxLen; j++)
                maxNum = max(maxNum, board[i][j]);
        return;
    }
    int temp[21][21];
    memcpy(temp, board, sizeof(board));    // 바뀌기 전 보드 저장
    int type = 4;
    while (type--)    // 4번 반복(상하좌우)
    {
        MovingBoard(type, moveCnt);
        memcpy(board, temp, sizeof(temp));    // 복사해놨던 보드로 다시 바꿈
    }
}
int main(void)
{
    cin >> maxLen;
    for (int i = 0; i < maxLen; i++)
        for (int j = 0; j < maxLen; j++)
            cin >> board[i][j];
    Solution(0);
    cout << maxNum << endl;
    return 0;
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

알고리즘 200일 프로젝트 - 14day

내일도 열심히!

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

백준 10448: 유레카 이론 (c++)  (0) 2020.04.21
백준 1748번: 수 이어 쓰기 1 (C++)  (0) 2020.04.20
백준 15683번: 감시 (C++)  (0) 2020.04.18
백준 1065번: 한수  (0) 2020.04.17
백준 15686번: 치킨 배달 (C++)  (0) 2020.04.15

[문제 링크]

 

15683번: 감시

스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감시할 수 있는 방법은 다음과 같다. 1번 CCTV는 한 쪽 방향만 감시할 수 있다. 2번과 3번은 두 방향을 감시할 수 있는데, 2번은 감시하는 방향이 서로 반대방향이어야 하고, 3번은 직각 방향이어야 한다. 4번은 세 방향, 5번은 네 방향을 감시할

www.acmicpc.net


내공이 부족한 것을 다시한번 뼈저리게 느낀 문제..

알고리즘은 다음과 같다.

대각선으로는 감시를 못하기 때문에 어떤 cctv든 한쪽 방향에 대해서 y좌표만 1증감하거나, x좌표만 1증감한다.

따라서 코드의 중복을 막기 위해 가로방향과 세로방향에 대해 탐색하는 함수를 만들어 호출하도록 하였다.

1번 cctv는 상 하 좌 우 4개의 경우의 수, 2번 cctv는 상하 좌우 2개의 경우의 수,

3번 cctv는 상좌, 상우, 하좌, 하우 4개의 경우의 수, 4번 cctv는 상좌우 상하좌 상하우 하좌우 4개 경우의 수,

5번은 1개의 경우의 수가 존재하기 때문에 사무실에 존재하는 cctv들의 모든 경우의 수에 대하여 완전탐색하면 원하는 출력을 얻을 수 있다.

실력이 부족하여 코드가 조잡하기 때문에.. 이해하기 힘들 수도 있습니다.


#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
 
const int INF = 987654321;
int maxCol, maxRow;
bool visited[8][8];
int result = INF;
vector<vector<int>> map;
int min(int a, int b) { return a < b ? a : b; }
void Solution();    // 전방선언
void ScanChange(int tempY, int tempX, int scanY, int scanX)
// CCTV가 볼 수 있는 0을 9로 바꿈
{
    if(scanX == 0)
        while (1)
        {
            tempY += scanY;
            if (tempY >= maxCol || tempY < 0break;
            if (map[tempY][tempX] == 6break;
            if (map[tempY][tempX] == 0)
                map[tempY][tempX] = 9;
        }
    else
        while (1)
        {
            tempX += scanX;
            if (tempX >= maxRow || tempX < 0break;
            if (map[tempY][tempX] == 6break;
            if (map[tempY][tempX] == 0)
                map[tempY][tempX] = 9;
        }
}
void GoScan(int y, int x, int type)
// CCTV 1번부터 5번까지 각각 다르게 동작
{
    vector<vector<int>> temp(map);
    int scan;
    switch (type)
    {
    case 1:
        scan = 1;
        for (int i = 0; i < 2; i++)
        {
            ScanChange(y, x, 0, scan);
            Solution();
            map = temp;
            ScanChange(y, x, scan, 0);
            Solution();
            map = temp;
            scan = -1;
        }
        break;
    case 2:
        ScanChange(y, x, 01);
        ScanChange(y, x, 0-1);
        Solution();
        map = temp;
 
        ScanChange(y, x, 10);
        ScanChange(y, x, -10);
        Solution();
        break;
    case 3:
        scan = 1;
        for (int i = 0; i < 2; i++)
        {
            ScanChange(y, x, scan, 0);
            ScanChange(y, x, 0, scan);
            Solution();
            map = temp;
 
            ScanChange(y, x, scan, 0);
            ScanChange(y, x, 0, scan*-1);
            Solution();
            map = temp;
            scan = -1;
        }
        break;
    case 4:
        ScanChange(y, x, -10);
        ScanChange(y, x, 0-1);
        ScanChange(y, x, 01);
        Solution();
        map = temp;
 
        ScanChange(y, x, 01);
        ScanChange(y, x, 10);
        ScanChange(y, x, 0-1);
        Solution();
        map = temp;
 
        ScanChange(y, x, -10);
        ScanChange(y, x, 0-1);
        ScanChange(y, x, 10);
        Solution();
        map = temp;
 
        ScanChange(y, x, -10);
        ScanChange(y, x, 01);
        ScanChange(y, x, 10);
        Solution();
        break;
    case 5:
        ScanChange(y, x, 01);
        ScanChange(y, x, 10);
        ScanChange(y, x, 0-1);
        ScanChange(y, x, -10);
        Solution();
        break;
    }
}
void Solution()
{
    int yPos = -1, xPos = -1;
    for (int i = 0; i < maxCol; i++)
    {
        for (int j = 0; j < maxRow; j++)
        {
            if (!visited[i][j] && map[i][j] != 0 && map[i][j] != 6 && map[i][j] != 9)
            {
                yPos = i;
                xPos = j;
                break;
            }
            if (yPos != -1break;    // 이중 for문 탈출
        }
    }
    if (yPos == -1)    // 기저사례. 모든 CCTV검사했을 시 사각지대 카운팅
    {
        int cnt = 0;
        for (int i = 0; i < maxCol; i++)
            for (int j = 0; j < maxRow; j++)
                if (map[i][j] == 0) cnt++;
        result = min(result, cnt);
        return;
    }
    visited[yPos][xPos] = true;
    GoScan(yPos, xPos, map[yPos][xPos]);
    visited[yPos][xPos] = false;
}
int main(void)
{
    cin >> maxCol >> maxRow;
    vector<int> temp;
    memset(visited, truesizeof(visited));
    for (int i = 0; i < maxCol; i++)
    {
        for (int j = 0; j < maxRow; j++)
        {
            int n;
            cin >> n;
            temp.push_back(n);
            if (n != 0 && n != 6)
                visited[i][j] = false;
        }
        map.push_back(temp);
        temp.clear();
    }
    Solution();
    cout << result << endl;
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

알고리즘 200일 프로젝트 - 13day

내일도 열심히!

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

백준 1748번: 수 이어 쓰기 1 (C++)  (0) 2020.04.20
백준 12100번: 2048(Easy) (C++)  (0) 2020.04.19
백준 1065번: 한수  (0) 2020.04.17
백준 15686번: 치킨 배달 (C++)  (0) 2020.04.15
백준 14500번: 테트로미노 (C++)  (0) 2020.04.15

+ Recent posts