괄호가 지워진 길이 50 이하의 덧셈과 뺄셈만 존재하는 식의 최소값을 구하는 문제입니다.

숫자는 99999 이하이며, 0부터 시작 할 수 있습니다.

식은 숫자로 시작하고 숫자로 끝나며, 연산자가 두개 이상 연속으로 입력되지 않습니다.

 

최소가 나오는 방법은 간단합니다.

- 연산자를 기점으로 괄호를 쳐서 그 안의 연산을 우선적으로 해주면 됩니다.

 

구현 방법으로는 입력되는 식을 -로 split 해주고, 각 substring을 다시 +로 split한 뒤 연산을 해줍니다.

그리고 그 결과물을 다시 - 연산을 해주면 됩니다.

 

이 간단한 문제를 저는 처음 시작하는 substring에도

+ 연산이 포함될 수 있다는 것을 간과하여 3번이나 실패를 했습니다.

정답율도 50% 언저리였는데 참 슬펐습니다.

 

더보기
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>

using namespace std;

const int StringToInt(const string& str)
{
    int ret = 0;
    for (unsigned int i = 0; i < str.size(); ++i)
    {
        ret *= 10;
        ret += str[i] - '0';
    }
    return ret;
}

const long long StringToList(const string& list)
{
    long long ret = 0;
    string temp;
    vector<string> pParse;
    stringstream ss(list);
    
    while (getline(ss, temp, '+'))
    {
        pParse.push_back(temp);
    }
    for (const auto& iter : pParse)
    {
        ret += StringToInt(iter);
    }
    return ret;
}

int main()
{
    long long ret = 0;
    string input, temp;
    vector<string> mParse;
    vector<int> mParseNum;

    cin >> input;
    stringstream ss(input);
    while (getline(ss, temp, '-'))
    {
        mParse.push_back(temp);
    }
    ret = StringToList(mParse[0]);
    for (unsigned int i = 1; i < mParse.size(); ++i)
    {
        ret -= StringToList(mParse[i]);
    }
    cout << ret << endl;

    return 0;
}

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

 

6064번: 카잉 달력

문제 최근에 ICPC 탐사대는 남아메리카의 잉카 제국이 놀라운 문명을 지닌 카잉 제국을 토대로 하여 세워졌다는 사실을 발견했다. 카잉 제국의 백성들은 특이한 달력을 사용한 것으로 알려져 있�

www.acmicpc.net

문제가 워낙 쉬워 보여 하나 더 풀어보았습니다.

S = {<x:y> | x = S % M, y = S % N}라고 했을 때 S를 구하라는 문제입니다.

간단히 두 Modular 연산 결과를 보고 원래 수를 구하라는 문제인데,

간단하게 하나씩 더해보았는데 정답을 맞출 수 있었습니다. 

 

단, x와 y중 하나를 기준으로 M과 N의 최소공배수 이상 더했음에도 답이 나오지 않으면

나올 수 없는 결과 값이므로 -1을 출력합니다.

사실 귀찮아서 최소공배수가 아니라 M * N까지 연산을 하였는데 아슬아슬하게 통과할 수 있었습니다.

 

이 문제를 언제 왜 못풀었나 살펴보니 4년 전이었습니다.

아마 대충 도전 했다가 놀았거나,

다국어로 되어 있는 걸로 보아 영어로 적힌 것을 해석하지 못하고 포기했던 것 같습니다.

 

더보기
#include <iostream>

using namespace std;

int main()
{
    int testcase = 0, M = 0, N = 0, x = 0, y = 0;
    cin >> testcase;
    while (testcase-- > 0)
    {
        int sum = 0;
        cin >> M >> N >> x >> y;
        while ((x != y) && (sum < (M * N)))
        {
            if (x > y)
            {
                y += N;
                sum += N;
            }
            else
            {
                x += M;
            }
        }
        if (sum >= (M * N))
        {
            cout << -1 << endl;
        }
        else
        {
            cout << x << endl;
        }
    }
}

 

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

 

10989번: 수 정렬하기 3

첫째 줄에 수의 개수 N(1 ≤ N ≤ 10,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 숫자가 주어진다. 이 수는 10,000보다 작거나 같은 자연수이다.

www.acmicpc.net

문제는 맞췄으나, 역시 혼자서는 맞추지를 못했습니다.

 

우선 어제 말한대로, 새로운 vector 선언을 최소화 한 Merge Sort를 구현하였습니다.

두 개의 subvector를 merge 할 때만 임시로 vector를 선언하였는데, 그럼에도 메모리가 부족하였습니다.

 

이 이상은 어떻게 줄일 방법이 없다고 판단하여 검색을 해보았습니다.

하지만 뜻밖에도, 문제는 다른 곳에 있었습니다.

 

대체로 다들 메모리와 시간 문제에 직면하는데,

다들 메모리 문제는 counting sort(입력값을 index로 하는 array에 갯수 저장)로 해결했습니다.

하지만 시간 문제는 알고리즘이 아니라 c스타일 array, c스타일 입출력.

그리고 입력의 최대값을 저장하여 출력 시 순회 횟수를 줄이는 것으로 시간을 줄였습니다.

 

대략적으로 시간복잡도를 계산하다보니 이런 부분은 신경쓰지 못한 것 같습니다.

다음에는 이런 부분까지도 항상 염두를 해두겠습니다.

 

더보기
#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
    int size = 0, temp = 0, max = 0;
    int arr[10000] = { 0 };
    
    cin >> size;
    for (int i = 0; i < size; ++i)
    {
        scanf("%d", &temp);
        max = temp > max ? temp : max;
        ++arr[temp - 1];
    }

    for (int i = 0; i < max; ++i)
    {
        if (arr[i] > 0)
        {
            for (int j = 0; j < arr[i]; ++j)
            {
                printf("%d\n", i + 1);
            }
        }
    }

    return 0;
}

+ Recent posts