[문제 링크]

 

1072번: 게임

각 줄에 X와 Y가 주어진다. X는 1,000,000,000보다 작거나 같은 자연수이고, Y는 0보다 크거나 같고, X보다 작거나 같은 자연수이다.

www.acmicpc.net


입력되는 숫자가 1~10억까지이므로 하나하나 검사하면 시간초과가 날 것이 분명하기 때문에 이분탐색을 이용해 풀었다.

충분히 큰 숫자(30억?)부터 시작해 이분탐색으로 더하기 전과 더한 후와 퍼센트가 일치하는 middle 구간을 찾고, 그 구간을 시작으로 1씩 더해가면서 퍼센트가 변하는 middle값을 찾으면 그 값이 정답이 된다.

추가적으로 입력받은 값의 승률이 99퍼센트 이상이면 아무리 더해도 100퍼센트가 나올 수 없기 때문에 불가능(-1)을 리턴 해주었다. 


#include <iostream>
using namespace std;
 
const long long MAX = 3000000000;
long long X, Y;
 
long long Solution()
{
    int winRate = (Y * 100/ X;
    if (winRate >= 99return -1;
    long long start = 0end = MAX;
    int result = -1;
    while (start <= end)
    {
        long long middle = (start + end/ 2;
        int tempWinRate = ((Y + middle) * 100/ (X + middle);
        if (tempWinRate == winRate)
        {
            result = middle + 1;
            start = middle + 1;
        }
        else
            end = middle - 1;
    }
    return result;
}
int main(void)
{
    cin >> X >> Y;
    cout << Solution() << endl;
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

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

내일도 열심히!

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

백준 1062번: 가르침  (0) 2020.04.29
백준 6679번: 싱기한 네자리 숫자  (0) 2020.04.28
백준 7453번: 합이 0인 네 정수  (0) 2020.04.26
백준 1038번: 감소하는 수  (0) 2020.04.25
백준 1051번 : 숫자 정사각형  (0) 2020.04.24

[문제 링크]

 

7453번: 합이 0인 네 정수

문제 정수로 이루어진 크기가 같은 배열 A, B, C, D가 있다. A[a], B[b], C[c], D[d]의 합이 0인 (a, b, c, d) 쌍의 개수를 구하는 프로그램을 작성하시오. 입력 첫째 줄에 배열의 크기 n (1 ≤ n ≤ 4000)이 주어진다. 다음 n개 줄에는 A, B, C, D에 포함되는 정수가 공백으로 구분되어져서 주어진다. 배열에 들어있는 정수의 절댓값은 최대 228이다. 출력 합이 0이 되는 쌍의 개수를 출력한다. 예제 입력 1 복

www.acmicpc.net


이 문제를 접했을 때 마침 STL 컨테이너 set, multiset, map, multimap 에 대해서 공부하고 난 뒤였다.

그래서 빠른 검색속도가 핵심인 multiset을 이용하여 구현해보려고 했었다.

A와 B를 모두 더한 순차열을 저장하고, C와 D를 모두 더한 순차열을 저장하는 두 개의 multiset 객체에

count 멤버함수를 사용하여 C와 D를 더한 객체에 -(A-B) 값(합쳐서 0이 되는 값)이 몇개 존재하는지 확인한 다음 갯수를 카운팅 하는 식으로 코드를 구현했는데 시간초과가 떴다. 연관 컨테이너(set, multiset, map, multimap)는 원소를 검색하는데 로그 시간 복잡도를 보장해준다고 배워서 시간 초과가 안나올줄 알았는데 시간초과가 나와서 당황했다.

구글링하다 접하게된 정보인데 아무래도 위에서 설명하는 특성때문에 시간초과가 난거같다. ㅜㅜ

 

그래서 vector컨테이너를 사용해서 구현하였다.

분명 multiset과 같이 이진 검색을 이용한 알고리즘인데 시간초과가 안난게 아직 풀리지 않은 의문이다.


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
vector<int> CD;
long long zeroSum = 0;
 
void Solution(int here)
{
    int lower_iter, upper_iter;
    lower_iter = lower_bound(CD.begin(), CD.end(), -here) - CD.begin();
    upper_iter = upper_bound(CD.begin(), CD.end(), -here) - CD.begin();
 
    if (lower_iter == upper_iter) return;
 
    zeroSum += upper_iter - lower_iter;
}
 
int main(void)
{
    int col;
    int a[4001], b[4001], c[4001], d[4001];
    cin >> col;
 
    for(int i=0; i<col; i++)
        cin >> a[i] >> b[i] >> c[i] >> d[i];
 
    for(int i=0; i<col; i++)
        for (int j = 0; j < col; j++)
            CD.push_back(c[i] + d[j]);
 
    sort(CD.begin(), CD.end());
 
    for (int i = 0; i < col; i++)
        for (int j = 0; j < col; j++)
            Solution(a[i] + b[j]);
 
    cout << zeroSum << endl;
 
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

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

내일도 열심히!

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

백준 6679번: 싱기한 네자리 숫자  (0) 2020.04.28
백준 1074번: 게임  (0) 2020.04.28
백준 1038번: 감소하는 수  (0) 2020.04.25
백준 1051번 : 숫자 정사각형  (0) 2020.04.24
백준 3085번: 사탕 게임 (c++)  (0) 2020.04.24

[문제 링크]

 

1038번: 감소하는 수

음이 아닌 정수 X의 자릿수가 가장 큰 자릿수부터 작은 자릿수까지 감소한다면, 그 수를 감소하는 수라고 한다. 예를 들어, 321과 950은 감소하는 수지만, 322와 958은 아니다. N번째 감소하는 수를 출력하는 프로그램을 작성하시오. 0은 0번째 감소하는 수이고, 1은 1번째 감소하는 수이다. 만약 N번째 감소하는 수가 없다면 -1을 출력한다.

www.acmicpc.net


큐를 이용한 솔루션을 생각하기 전에 한참 고민한 문제였다.

큐의 첫번째 원소의 일의 자리 수 보다 작은 숫자들을 뒤에 붙여서 다시 큐에 추가하는식으로 구현하였다.


#include <iostream>
#include <queue>
using namespace std;
 
queue<long long> q;
long long Solution(int N)
{
    if (N == 0return 0;
    int lastNum, cnt = 0;
    for (int i = 1; i < 10; i++)
        q.push(i);
    while (!q.empty())
    {
        int lastNum = q.front() % 10;
        for (int i = 0; i < lastNum; i++)
            q.push((q.front() * 10+ i);
        cnt++;
        if (cnt == N) return q.front();
        q.pop();
    }
    return -1;
}
int main(void)
{
    int N;
    cin >> N;
    cout << Solution(N) << endl;
    return 0;
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

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

내일도 열심히!

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

백준 1074번: 게임  (0) 2020.04.28
백준 7453번: 합이 0인 네 정수  (0) 2020.04.26
백준 1051번 : 숫자 정사각형  (0) 2020.04.24
백준 3085번: 사탕 게임 (c++)  (0) 2020.04.24
백준 2503번: 숫자 야구 (c++)  (0) 2020.04.23

[문제 링크]

 

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

+ Recent posts