[문제 링크]

 

1992번: 쿼드트리

첫째 줄에는 영상의 크기를 나타내는 숫자 N 이 주어진다. N 은 언제나 2의 제곱수로 주어지며, 1≤N ≤64의 범위를 가진다. 두 번째 줄부터는 길이 N 의 문자열이 N 개 들어온다. 각 문자열은 0 또는 1의 숫자로 이루어져 있으며, 영상의 각 점들을 나타낸다.

www.acmicpc.net


https://onlytrying.tistory.com/42

AOJ의 QUADTREE 문제와 유사한 형태의 문제라고 생각한다. 따라서 알고리즘도 비슷하게 구현하였다.

먼저 (startY, startX)좌표를 시작으로 N X N 크기만큼 보드값을 검사한다. 모든 값이 일치한다면 숫자 1 or 0 으로 압축할 수 있다. 값이 일치하지 않다면 N/2 크기의 보드 4개로 나누고 나눠진 보드에 대해 위와 같은 작업을 반복한다.

나눠진 보드들이 반환하는 문자열을 합치고 시작 위치에 '(', 끝 위치에 ')'을 붙여주면 원하는 결과를 출력할 수 있다.


#include <iostream>
#include <string>
#include <vector>
using namespace std;

vector<string> board;

string Solution(int N, int startY, int startX)
{
	bool check = true;
	for (int i = startY; i < startY+N; i++)
	{
		for (int j = startX; j < startX+N; j++)
		{
			if (board[i][j] != board[startY][startX])
			{
				check = false;
				break;
			}
		}
		if (!check) break;
	}
	if (check) return string(1,board[startY][startX]);

	int nextN = N / 2;
	string board1 = Solution(nextN, startY, startX);
	string board2 = Solution(nextN, startY, startX + nextN);
	string board3 = Solution(nextN, startY + nextN, startX);
	string board4 = Solution(nextN, startY + nextN, startX + nextN);

	return '(' + board1 + board2 + board3 + board4 + ')';
}
int main(void)
{
	int N;
	cin >> N;
	for (int i = 0; i < N; i++)
	{
		string str;
		cin >> str;
		board.push_back(str);
	}
	cout << Solution(N, 0, 0) << endl;
	
	return 0;
}

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

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

백준 6236번: 용돈 관리  (0) 2020.05.13
백준 1780번: 종이의 개수  (0) 2020.05.12
백준 1074번: Z  (2) 2020.05.12
백준 11729번: 하노이 탑 이동 순서  (0) 2020.05.11
백준 2966번: 찍기  (0) 2020.05.06

[문제 링크]

1074번: Z

한수는 2차원 배열 (항상 2^N * 2^N 크기이다)을 Z모양으로 탐색하려고 한다. 예를 들어, 2*2배열을 왼쪽 위칸, 오른쪽 위칸, 왼쪽 아래칸, 오른쪽 아래칸 순서대로 방문하면 Z모양이다. 만약, 2차원 배열의 크기가 2^N * 2^N라서 왼쪽 위에 있는 칸이 하나가 아니라면, 배열을 4등분 한 후에 (크기가 같은 2^(N-1)로) 재귀적으로 순서대로 방문한다. 다음 예는 2^2 * 2^2 크기의 배열을 방문한 순서이다. N이 주어졌을 때, (r,

www.acmicpc.net


2^N X 2^N 크기의 보드가 주어졌을 때, 이를 4등분 하면 2^(N-1) X 2^(N-1) 보드 4개로 나뉘게 된다.

또한 입력받은 좌표는 반드시 4개의 보드 중 한개의 보드 내에 존재하게 된다. 입력받은 좌표를 포함하는 보드에 대해 계속 나누면서 나뉜 보드의 크기가 2^1 X 2^1 이 되었을 때, 선택된 2X2 크기의 보드에는 반드시 입력받은 좌표가 존재하게 된다.

좌표와 일치하는 블록이 전체 보드판에서 가지는 값(방문 순서)을 출력해주면 원하는 결과를 얻을 수 있다.


#include <iostream>
#include <cmath>
using namespace std;

int Solution(int N, int col, int row, int start, int findCol, int findRow)
{
	if (N == 1)
	{
		if (col == findCol && row == findRow) return start;
		else if (col == findCol && row + 1 == findRow) return start + 1;
		else if (col + 1 == findCol && row == findRow) return start + 2;
		else return start + 3;
	} 

	int halfCol = pow(2, N) / 2 + col;
	int halfRow = pow(2, N) / 2 + row;

	if (findCol < halfCol && findRow < halfRow)
		return Solution(N - 1, col, row, start, findCol, findRow);

	else if (findCol < halfCol && findRow >= halfRow)
		return Solution(N - 1, col, halfRow, start + pow((pow(2,N)/2),2), findCol, findRow);

	else if (findCol >= halfCol && findRow < halfRow)
		return Solution(N - 1, halfCol, row, start + pow((pow(2, N)/2), 2) * 2, findCol, findRow);

	else
		return Solution(N - 1, halfCol, halfRow, start + pow((pow(2, N)/2) , 2) * 3, findCol, findRow);
}

int main(void)
{
	int N, r, c;
	cin >> N >> r >> c;
	cout << Solution(N, 0, 0, 0, r, c) << endl;
}

 

 

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

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

백준 1780번: 종이의 개수  (0) 2020.05.12
백준 1992번: 쿼드트리  (0) 2020.05.12
백준 11729번: 하노이 탑 이동 순서  (0) 2020.05.11
백준 2966번: 찍기  (0) 2020.05.06
백준 4641번: Doubles  (0) 2020.05.06

[문제 링크]

 

11729번: 하노이 탑 이동 순서

세 개의 장대가 있고 첫 번째 장대에는 반경이 서로 다른 n개의 원판이 쌓여 있다. 각 원판은 반경이 큰 순서대로 쌓여있다. 이제 수도승들이 다음 규칙에 따라 첫 번째 장대에서 세 번째 장대로 옮기려 한다. 한 번에 한 개의 원판만을 다른 탑으로 옮길 수 있다. 쌓아 놓은 원판은 항상 위의 것이 아래의 것보다 작아야 한다. 이 작업을 수행하는데 필요한 이동 순서를 출력하는 프로그램을 작성하라. 단, 이동 횟수는 최소가 되어야 한다. 아래 그림은 원판이 5

www.acmicpc.net


하노이탑은 1번 막대(from)에서 시작하는 경우 2번 막대(by)를 거쳐 3번 막대(to)에 쌓는다.

 

즉 1번 막대(from)에서 마지막 원판을 제외한 n-1개 원판을 3번 막대(to)를 거쳐 2번 막대(by)에 쌓은 다음, 남은 원판을 목적지인 3번 막대(to)에 쌓고, 원판이 쌓인 막대가 바뀌었으니 똑같이 2번 막대에서 1번 막대를 거쳐 3번 막대에 쌓는 작업을 반복하는 것이다.

 

이는 움직이기 전 하노이탑에서 시작 지점과 원판 갯수(n)만 바뀐 같은 문제가 반복되는 형태라는 것을 알 수 있고, 이는 분할 정복 알고리즘을 통해 해결할 수 있다.

 

하노이탑 이동 횟수는 원판수(n)에 따라 정해진 공식이 있지만, 본 코드에서는 cnt라는 변수로 횟수를 카운팅하고, 이동 경로를 queue에 담아 마지막에 출력해주는 형태로 구현하였다.


#include <iostream>
#include <queue>
using namespace std;

queue<pair<int, int>> moving;
int cnt;
void hanoi(int n, int from, int by, int to) // from에서 by를 거쳐 to로
{
	if (n == 1)
	{
		moving.push(make_pair(from, to));
		cnt++;
	}
	else
	{
		hanoi(n - 1, from, to, by);
		moving.push(make_pair(from, to));
		cnt++;
		hanoi(n - 1, by, from, to);
	}
}

int main(void)
{
	int n;
	cin >> n;
	hanoi(n, 1, 2, 3);
	cout << cnt << endl;
	while (!moving.empty())
	{
		cout << moving.front().first << ' ' << moving.front().second << '\n';
		moving.pop();
	}
	return 0;
}

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

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

백준 1992번: 쿼드트리  (0) 2020.05.12
백준 1074번: Z  (2) 2020.05.12
백준 2966번: 찍기  (0) 2020.05.06
백준 4641번: Doubles  (0) 2020.05.06
백준 2858번: 기숙사 바닥  (0) 2020.05.05

[문제 링크]

algospot.com :: FENCE

울타리 잘라내기 문제 정보 문제 너비가 같은 N개의 나무 판자를 붙여 세운 울타리가 있습니다. 시간이 지남에 따라 판자들이 부러지거나 망가져 높이가 다 달라진 관계로 울타리를 통째로 교체하기로 했습니다. 이 때 버리는 울타리의 일부를 직사각형으로 잘라내 재활용하고 싶습니다. 그림 (b)는 (a)의 울타리에서 잘라낼 수 있는 많은 직사각형 중 가장 넓은 직사각형을 보여줍니다. 울타리를 구성하는 각 판자의 높이가 주어질 때, 잘라낼 수 있는 직사각형의 최대

algospot.com


분할정복은 문제를 부분 문제로 뚝 자르고 잘라져서 나온 조각에 대해 똑같이 처음 했던 것처럼 뚝 자르기를 반복하여 정답을 찾아내는 방식인거같다.

다만 완전탐색과 조금 다른점이 있다면 문제마다 구현해야할 기저사례, 점화식을 깊게 생각해봐야하고, 이를 구현하는 것이 까다롭다는 것이다. 대강 원리는 이해했으니 문제를 많이 풀어보면서 문제 유형에 익숙해지고 구현력을 키워야겠다.


#include <iostream>

#include <vector>

using namespace std;

 

vector<int> fence;

inline int max(const int a, const int b)

{

    return a > b ? a : b;

}

inline int min(const int a, const int b)

{

    return a < b ? a : b;

}

int Solution(int left, int right)

{

    if (left == right) return fence[left];

    int mid = (left + right) / 2;

    int ret = max(Solution(left, mid), Solution(mid + 1, right));

    int lt = mid, rt = mid+1;

    int height = min(fence[lt], fence[rt]);

    ret = max(ret, height * 2);

 

    while (left < lt || rt < right)

    {

        if (rt < right && (left == lt || fence[lt-1< fence[rt+1]))

        {

            rt++;

            height = min(height, fence[rt]);

        }

        else

        {

            lt--;

            height = min(height, fence[lt]);

        }

        ret = max(ret, height * (rt - lt + 1));

    }

    return ret;

}

 

int main(void)

{

    int testcase;

    cin >> testcase;

    while (testcase--)

    {

        int num, w;

        cin >> num;

        for(int i =0; i<num; i++)

        {

            cin >> w;

            fence.push_back(w);

        }

        cout << Solution(0,num-1<< endl;

        fence.clear();

    }

}

Colored by Color Scripter

 

 

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

[문제 링크]

 

algospot.com :: QUADTREE

쿼드 트리 뒤집기 문제 정보 문제 대량의 좌표 데이터를 메모리 안에 압축해 저장하기 위해 사용하는 여러 기법 중 쿼드 트리(quad tree)란 것이 있습니다. 주어진 공간을 항상 4개로 분할해 재귀적으로 표현하기 때문에 쿼드 트리라는 이름이 붙었는데, 이의 유명한 사용처 중 하나는 검은 색과 흰 색밖에 없는 흑백 그림을 압축해 표현하는 것입니다. 쿼드 트리는 2N × 2N 크기의 흑백 그림을 다음과 같은 과정을 거쳐 문자열로 압축합니다. 이 그림의 모든

algospot.com


분할정복 알고리즘 부분은 교재에 나와있는 소스코드와 동일하다.

다만 책에서 설명이 안되어있는데, 매개변수로 반복자를 참조하기 위해서는 비 const 반복자를 전달해야한다.

tree.begin() 이 반환하는 반복자는 const 반복자이므로 따로 비 const 반복자를 선언하고 tree.begin()으로 초기화해줘야 한다는 점만 주의하면 될 것 같다.


#include <iostream>
#include <string>
using namespace std;

string Reverse(string::iterator& iter)

{

    char head = *iter;

    iter++;

    if (head == 'w' || head == 'b'return string(1, head);

 

    string upperLeft = Reverse(iter);

    string upperRight = Reverse(iter);

    string lowLeft = Reverse(iter);

    string lowRight = Reverse(iter);

 

    return string("x"+ lowLeft + lowRight + upperLeft + upperRight;

}

int main(void)

{

    int testcase;

    cin >> testcase;

    string tree;

    while (testcase--)

    {

        cin >> tree;

        string::iterator iter = tree.begin();

        cout << Reverse(iter) << endl;

    }

}

Colored by Color Scripter

 

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

[문제 링크]

 

2966번: 찍기

문제 상근이, 창영이, 현진이는 역사와 전통을 자랑하는 Sogang ACM-ICPC Team에 가입하려고 한다. 하지만, 가입하려고 하는 모든 지원자는 C언어 필기시험을 통과해야 한다. 이들은 C언어를 할 줄 모른다. 따라서, 필기시험을 모두 찍으려고 한다. 상근이는 A, B, C, A, B, C, A, B, C, A, B, C, ...와 같이 찍어야 통과할 수 있다고 생각한다.  하지만, 창영이는 B, A, B, C, B, A, B, C, B, A, B

www.acmicpc.net


string 컨테이너와 반복자를 사용하여 손쉽게 해결한 문제였다.

Adrian의 찍는 순서는 "ABC", Bruno의 찍는 순서는 "BABC", Goran의 찍는 순서는 "CCAABB" 임을 알 수 있기 때문에

찍는 순서를 string에 저장하고 반복자를 한칸씩 증가시키는 방법으로 입력된 문자열과 비교하였다.


 
#include <iostream>
#include <string>
using namespace std;
 
int max(const int a, const int b)
{
    return a > b ? a : b;
}
int max(const int a, const int b, const int c)
{
    return a > max(b, c) ? a : max(b, c);
}
int main(void)
{
    int len, AdrCnt = 0, BruCnt = 0, GoCnt = 0;
    string problem, Adrian("ABC"), Bruno("BABC"), Goran("CCAABB");
    cin >> len >> problem;
 
    string::iterator AdrIter = Adrian.begin(), BruIter = Bruno.begin(), GoIter = Goran.begin();
    for (int i = 0; i < len; i++)
    {
        if (problem[i] == *AdrIter++) AdrCnt++;
        if (AdrIter == Adrian.end()) AdrIter = Adrian.begin();
 
        if (problem[i] == *BruIter++) BruCnt++;
        if (BruIter == Bruno.end()) BruIter = Bruno.begin();
 
        if (problem[i] == *GoIter++) GoCnt++;
        if (GoIter == Goran.end()) GoIter = Goran.begin();
    }
 
    int maxNum = max(AdrCnt, BruCnt, GoCnt);
    cout << maxNum << endl;
    if (AdrCnt == maxNum) cout << "Adrian" << endl;
    if (BruCnt == maxNum) cout << "Bruno" << endl;
    if (GoCnt == maxNum) cout << "Goran" << endl;
    
    return 0;
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

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

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

백준 1074번: Z  (2) 2020.05.12
백준 11729번: 하노이 탑 이동 순서  (0) 2020.05.11
백준 4641번: Doubles  (0) 2020.05.06
백준 2858번: 기숙사 바닥  (0) 2020.05.05
백준 1405번: 미친 로봇  (0) 2020.05.03

[문제 링크]

 

4641번: Doubles

문제 2~15개의 서로 다른 자연수로 이루어진 리스트가 있을 때, 이들 중 리스트 안에 자신의 정확히 2배인 수가 있는 수의 개수를 구하여라. 예를 들어, 리스트가 "1 4 3 2 9 7 18 22"라면 2가 1의 2배, 4가 2의 2배, 18이 9의 2배이므로 답은 3이다. 입력 입력은 여러 개의 테스트 케이스로 주어져 있으며, 입력의 끝에는 -1이 하나 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있으며, 2~15개의 서로 다른 자연수가 주어진다.

www.acmicpc.net


 

입력받은 숫자들을 전부 vector에 담아 2중 for문을 돌려도 정답은 쉽게 찾을 수 있겠지만, 효율성을 늘리기 위해 하나의 for문을 사용하는 쪽으로 구현하였다.

자연수의 최대값이 100을 넘지 않기 때문에 계수정렬을 이용하였고, for_each 함수를 사용하여 벡터에 담긴 모든 원소를 탐색하였다.


#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
 
int numberCnt[101], result;
 
void Pred(const int a)
{
    result += numberCnt[a*2];
}
int main(void)
{
    vector<int> v;
    while (1)
    {
        result = 0;
        memset(numberCnt, 0sizeof(numberCnt));
        while (1)
        {
            int num;
            cin >> num;
            if (num == -1return 0;
            else if (num == 0break;
            v.push_back(num);
            numberCnt[num]++;
        }
        for_each(v.begin(), v.end(), Pred);
        v.clear();
        cout << result << endl;
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

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

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

백준 11729번: 하노이 탑 이동 순서  (0) 2020.05.11
백준 2966번: 찍기  (0) 2020.05.06
백준 2858번: 기숙사 바닥  (0) 2020.05.05
백준 1405번: 미친 로봇  (0) 2020.05.03
백준 1213번: 팰린드롬 만들기  (0) 2020.04.30

[문제 링크]

 

2858번: 기숙사 바닥

문제 상근이는 기숙사 생활을 한다. 상근이의 방의 크기는 L*W 이다. 수업시간에 타일 채우기 경우의 수를 계산하던 상근이는 자신의 방도 1*1크기 타일로 채우려고 한다. 이때, 가장자리는 빨간��

www.acmicpc.net


갈색타일(B)의 개수는 빨간타일(R)이 몇 줄로 이루어져 있느냐에 따라 달라진다.

따라서 빨간타일(R)이 1줄 일 때 부터 (R/2)줄 까지 갈색타일 개수를 구하고 입력받은 B와 일치할 때 결과를 출력해주면 원하는 정답을 얻을 수 있다.


#include <iostream>
using namespace std;
 
int main(void)
{
    int R, B;
    cin >> R >> B;
    int i = 0;
    while (++i)
    {
        if (B % i == 0)
        {
            int row = B / i;
            if ((row + i + 2* 2 == R)
            {
                cout << row + 2 << ' ' << i + 2 << endl;
                break;
            }
        }
        else continue;
    }
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

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

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

백준 2966번: 찍기  (0) 2020.05.06
백준 4641번: Doubles  (0) 2020.05.06
백준 1405번: 미친 로봇  (0) 2020.05.03
백준 1213번: 팰린드롬 만들기  (0) 2020.04.30
백준 2981번: 검문  (0) 2020.04.30

+ Recent posts