#문제 해결 방법

 

가장 중요한 생각은

S ->T로 가는건 가지수가 많기 때문에

시간초과가 나기 매우매우 쉽다는것이다.

혹시 하더라도 일치하는지 확인하는 조건때문에 kmp 가 필요할지도 모르겟다.

 

때문에 T->S 로 가는 것은 매우 가지수가 적다.

왜냐면 뒤에 A가 있다면 A를 추가한것이기 때문에 빼주고

B가 잇다면 B를 뒤집고 추가해준거라 빼고 뒤집어 주면된다

 

이 힌트를 알 수 있는것은

바로 추가하는 방향이 한쪽으로만 이뤄진다는 것이다.

 

만약 양방향으로 추가가 되었다면 불가능했을 것이다.

 

#전체 코드

#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
using namespace std;





int main() {
    string s,t;
    cin >> s >> t;



    while (true) {

        if (t[t.length() - 1] == 'A') {
            t.pop_back();
        }
        else {
            t.pop_back();
            reverse(t.begin(), t.end());
        }

        if (t.length() == s.length()) {
            if (s == t) {
                cout << 1 << '\n';
            }
            else {
                cout << 0 << '\n';
            }
            break;
        }
    }


    return 0;
}

'[백준] > C++' 카테고리의 다른 글

백준 1059번 좋은 구간 [C++]  (0) 2024.07.25
백준 1522번 문자열 교환 [C++]  (6) 2024.07.24
백준 31962번 밤양갱 [C++]  (3) 2024.07.23
백준 8972번 미친 아두이노 [C++]  (0) 2024.07.18
백준 2638번 치즈 [C++]  (0) 2024.07.18

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

 

 

 

 

#문제 해결 방법

 

우선 재일 달디달고를 입력하는데는 8회가 걸린다.

그 이후에 달디달고를 연속해서 입력했을때

4개를 만들어야 된다면 2개를 만들고 2개를 복사 할 수 잇다.

8개를 만들어야 된다면 4개를 만들고 복사할 수 있다.

 

즉 남은 달디달고가 현재 만든 달디달고 의 배수보다 많이 남았다면 

1초가 걸리게 된다.

 

마지막의 달디단은 +1초로 결정해 주면 된다.

왜냐하면 daldida 까지 2의 배수를 복사해오면서 같이 복사해오면 되기 때문이다

 

그이후에 n 붙이는데 +1초로 이걸 만들어 주면 된다.

 

 

#전체 코드

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



int main() {
    
    int n;
    cin >> n;

    int count = 0;
    if (n == 1) {
        count = 10;
    }
    else if (n == 2) {
        count = 11;
    }
    else if (n >= 3) {
        int temp = 1;
        while (temp <= n) {
            if (temp * 2 <= n) {
                temp *= 2;
                count++;
            }
            else{
                count += 2;
                break;
            }
        }
        count += 8;
    }

    cout << count << '\n';
    return 0;
}

'[백준] > C++' 카테고리의 다른 글

백준 1522번 문자열 교환 [C++]  (6) 2024.07.24
백준 12904번 A와 B [C++]  (1) 2024.07.23
백준 8972번 미친 아두이노 [C++]  (0) 2024.07.18
백준 2638번 치즈 [C++]  (0) 2024.07.18
백준 10703번 유성 [C++]  (0) 2024.07.11

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

 

 

 

#문제 간단 정리

시뮬레이션 문제..

천천히 구현을 하자

 

#문제 해결 방법

 

1.종수가 움직임

    -> 만약 움직일 위치에 로봇이있다면 이동횟수 출력하고 종료

2. 로봇이 움직임

    -> 8개의 방향에 대해서 가장 종수랑 가까워 지는 방향을 계산

    -> 2차원배열에 로봇들의 개수를 입력

    ->2개이상이면  '.'으로 1개라면 'R'로 맵에 입력 0개라면 로봇이 없으니 '.'로 입력

 

#전체 코드

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

int dx[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };
int dy[9] = { 1, 1, 1, 0, 0, 0, -1, -1, -1 };

vector<vector<char>> world;
pair<int, int> jong;
vector<pair<int, int>> robots;
int r, c;
int moveCount;

bool boundary(int y, int x) {
    return (0 <= y && y < r && 0 <= x && x < c);
}

bool moveJong(int input) {
    int ny = jong.first + dy[input];
    int nx = jong.second + dx[input];

    if (world[ny][nx] == 'R') {
        cout << "kraj " << moveCount + 1 << '\n';
        return false;
    }
    else {
        world[jong.first][jong.second] = '.';
        jong = { ny, nx };
        world[ny][nx] = 'I';
        moveCount++;
        return true;
    }
}

void moveRobot() {
    vector<vector<int>> newPos(r, vector<int>(c, 0));
    vector<pair<int, int>> newRobots;

    for (auto& robot : robots) {
        int minDist = 1e9;
        int bestY = robot.first, bestX = robot.second;

        for (int i = 0; i < 9; i++) {
            int ny = robot.first + dy[i];
            int nx = robot.second + dx[i];
            if (boundary(ny, nx)) {
                int dist = abs(ny - jong.first) + abs(nx - jong.second);
                if (dist < minDist) {
                    minDist = dist;
                    bestY = ny;
                    bestX = nx;
                }
            }
        }

        if (world[bestY][bestX] == 'I') {
            cout << "kraj " << moveCount << '\n';
            exit(0);
        }
        newPos[bestY][bestX]++;
        newRobots.push_back({ bestY, bestX });
    }

    robots.clear();
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            if (newPos[i][j] == 1) {
                robots.push_back({ i, j });
                world[i][j] = 'R';
            }
            else if (newPos[i][j] > 1) {
                world[i][j] = '.';
            }
            else if (newPos[i][j] == 0) {
                world[i][j] = '.';
            }
        }
    }
    world[jong.first][jong.second] = 'I';
}

int main() {
    cin >> r >> c;
    world.resize(r, vector<char>(c));

    for (int i = 0; i < r; i++) {
        string s;
        cin >> s;
        for (int j = 0; j < c; j++) {
            world[i][j] = s[j];
            if (s[j] == 'I') {
                jong = { i, j };
            }
            else if (s[j] == 'R') {
                robots.push_back({ i, j });
            }
        }
    }

    string command;
    cin >> command;
    moveCount = 0;

    for (char cmd : command) {
        if (!moveJong(cmd - '1')) {
            return 0;
        }
        moveRobot();
    }

    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            cout << world[i][j];
        }
        cout << '\n';
    }

    return 0;
}

'[백준] > C++' 카테고리의 다른 글

백준 12904번 A와 B [C++]  (1) 2024.07.23
백준 31962번 밤양갱 [C++]  (3) 2024.07.23
백준 2638번 치즈 [C++]  (0) 2024.07.18
백준 10703번 유성 [C++]  (0) 2024.07.11
백준 1456번 거의 소수 [C++]  (0) 2024.07.08

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

 

 

#문제 해결 방법

 

친절하게도 가장자리에는 치즈가 놓이지 않는다고 했으니

외곽부터 외부공기를 탐색하고 난 후 남은 공기는

내부 공기로 취급하면 된다.

 

나는 외부 공기를 그냥 bool 배열을 사용해서 따로 표시했다.

기존의 맵이랑 같이 표시하는 방법이 더 효율이 좋을 듯 한데 

그냥 더 직관적인 방법을 사용했다.

 

1.외부공기를 확인한 후에

2. 외부공기 2개가 맞닿은 치즈 확인 -> 지우기

        findOx(0, 0);
        cheeseCheck();

를 반복하고 

치즈가 0이 될때 까지 반복된 순서를 출력 하면 된다.

 

#전체 코드

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

int dx[4] = { -1,0,1,0 };
int dy[4] = { 0,1,0,-1 };
int cheeseCount;
int n, m;
vector<vector<int>> world;
vector<vector<bool>> check;

bool boundary(int x, int y) {
    if (0 <= x && x < n && 0 <= y && y < m) return true;

    return false;
}

void findOx(int x, int y) {

    for (int i = 0; i < 4; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];
        if (boundary(nx, ny)) {
            if (world[nx][ny] == 0 && check[nx][ny] == false) {
                check[nx][ny] = true;
                findOx(nx, ny);
            }
        }

    }

}
void cheeseCheck() {
    for (int a = 0; a < n; a++) {
        for (int b = 0; b < m; b++) {
            if (world[a][b] == 1) {
                int oxCount = 0;
                for (int i = 0; i < 4; i++) {
                    int nx = a + dx[i];
                    int ny = b + dy[i];
                    if (boundary(nx, ny)) {
                        if (check[nx][ny] == true) {
                            oxCount++;
                        }
                    }

                }
                if (oxCount >= 2) {
                    world[a][b] = 0;
                    cheeseCount--;
                }
            }
        }
    }
}






int main() {
    //1. 일단 공기를 돌면서 치즈에 갖혀있는지 아닌지 판별한다
    // ->가장자리 공기를 탐색하고 외부 탐색이 안 되었다면 내부 공기
    //2.치즈를 녹이고 시간을 보낸후 치즈가 0개라면 시간 출력



    cin >> n >> m;
    world.resize(n, vector<int>(m, 0));


    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> world[i][j];
            if (world[i][j] == 1) cheeseCount++;
        }
    }

    int phase = 0;
    while (cheeseCount > 0) {
        check.assign(n, vector<bool>(m, false));
        //외부 공기 확인
        check[0][0] = true;
        findOx(0, 0);
        //접촉 치즈 확인
        cheeseCheck();

        phase++;
    }

    cout << phase << '\n';

    return 0;
}

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

 

#문제 간단 정리

   //만약 가장 낮은 위치에 있는 유성과
   //그 열에 가장 낮은 위치의 유성 - 가장 높은 위치에 있는 땅
   //그 값들의 최소값 만큼 내려 올 수 있다.

 

#문제 해결 방법

 

전반적으로 구현 문제기 때문에 위와 같이 해결 할 수 있는데

 

반례를 잘 찾아야 될 것 같다.

 

일단 주어진 테스트케이스에서는 무조건 땅이 존재 하는것 같다.

그래서 땅이 없는 경우에는 테스트케이스가 존재  하지 않는 것 같고

 

 

땅이 있는부분과 없는 부분이 나눠진 테스트케이스가 존재하는 것 같은데

이 경우에는 땅이 있는 곳의 유성과의 차이만큼 내려주도록 구현을 해야 된다.

 

만약 전부 땅이 없는 경우에는 내 코드는 오류가나는데

이는 상정 안된 부분인듯하지만 딱히 명시는 안되있다.

 

#전체 코드

#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <cmath>
#include <climits>

using namespace std;

int main() {
    
    int r, s;
    cin >> r >> s;

    //만약 가장 낮은 위치에 있는 유성과
    //그 열에 가장 낮은 위치의 유성 - 가장 높은 위치에 있는 땅
    //그 값들의 최소값 만큼 내려 올 수 있다.
    
    vector<vector<char>> board(r,vector<char>(s));
    for (int i = 0; i < r; i++) {
        string input;
        cin >> input;

        //board 에 입력
        for (int j = 0; j < s; j++) {
            board[i][j] = input[j];
        }
    }

    int minDiff = INT_MAX;

    //열을 순회하면서 가장 작은 차이를 고른다
    for (int i = 0; i < s; i++) {
        int maxMeteor = -1;
        int maxGround = INT_MAX;
        for (int j = 0; j < r; j++) {
            if (board[j][i] == 'X') {
                maxMeteor = j;
            }
            if (board[j][i] == '#' && maxGround == INT_MAX) {
                maxGround = j;
            }
        }
        // 유성이 있고, 그 아래에 땅이 있는 경우만 계산
        if (maxMeteor != -1 && maxGround != INT_MAX) {
            minDiff = min(maxGround - maxMeteor , minDiff);
        }
    }


    //minDiff 만큼 유성을 아래로 내린다.
    //아래부터 탐색해서 중복을 없앤다
    for (int i = r - 1; i >= 0; i--) {
        for (int j = 0; j < s; j++) {
            if (board[i][j] == 'X') {
                board[i][j] = '.';
                board[i + minDiff-1][j] = 'X';
            }
        }
    }


    //복원 후 출력
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < s; j++) {
            cout << board[i][j];
        }
        cout << '\n';
    }

    return 0;
}

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

 

 

 

 

#문제 해결 방법

 

우선 문제를 살펴 봤을 때

 

소수를 에라토스테네스의 체로 구한다는 생각은 쉽게 할 수 있다.

 

그리고 거의 소수를 (소수의 n제곱) 을 구하는건

딱히 추가적으로 빠른 방법이 없다 생각이 되어서

브루트 포스로 풀어야 겠다는 생각이 먼저 든다.

 

 

그래서 에라토스테네스로

루트 b 까지의 소수를 구하는데

이유는

거의 소수는 소수의 n 제곱이라

루트 b 이상의 소수는 필요 없기 때문이다


    ll limit = sqrt(b) + 1;
    vector<bool> is_prime(limit + 1, true);
    vector<ll> primes;

 

그리고 구한 소수들을 계속 제곱해 가면서 b를 넘지 않고

a 보다 크다면 거의소수를 찾은 것이다.

 

    int count = 0;
    for (ll i : primes) {
        ll temp = i*i;

        while (temp <= b) {
            if (temp >= a) {
                count++;
            }
            if (temp > b /i) break; // 오버플로우 방지
            temp *= i;
        }

    }

 

여기서 주의 할 것은 오버플로우 방지를 하지 않는다면 

틀리니까 오버플로우 방지를 주의하자 

 

#전체 코드

#include <iostream>
#include <string>
#include <istream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;

typedef long long ll;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    ll a, b;
    cin >> a >> b;


    ll limit = sqrt(b) + 1;
    vector<bool> is_prime(limit + 1, true);
    vector<ll> primes;

    // 에라토스테네스의 체로 sqrt(b)까지의 소수를 구함
    is_prime[0] = is_prime[1] = false;
    for (ll i = 2; i <= limit; ++i) {
        if (is_prime[i]) {
            primes.push_back(i);
            for (ll j = i * i; j <= limit; j += i) {
                is_prime[j] = false;
            }
        }
    }

    int count = 0;
    for (ll i : primes) {
        ll temp = i*i;

        while (temp <= b) {
            if (temp >= a) {
                count++;
            }
            if (temp > b /i) break; // 오버플로우 방지
            temp *= i;
        }

    }

    cout << count << '\n';

    return 0;
}

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

 

 

 

#해결 방법

 

일단 그냥 구현 그자체인데

 

소수점 처리에서 아주 귀찮다.

 

입력값의 소수점을 지우기 위해서 

 

            long long combo_bonus = 100 + combo * C;
            long long skill_bonus = 100 + skill[idx] * s[idx];

 

각각 100을 곱해준 상태로 처리하고

10'000을 나눠주고

소수점 내림을해서 처리하도록하자

 

즉 소수가 나올거같을때는 곱해서 소수점을 없애고 나중에 나눠서 

오차를 줄이도록하자

 

#전체 코드

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

int main() {
    int N, K, C, R;
    cin >> N >> K >> C >> R;

    vector<int> base(K);
    vector<int> s(K);
    vector<int> p(K);

    for (int i = 0; i < K; i++) {
        cin >> base[i];
    }
    for (int i = 0; i < K; i++) {
        cin >> s[i];
    }
    for (int i = 0; i < K; i++) {
        cin >> p[i];
    }

    vector<int> skill(K, 0);
    int combo = 0;
    int stress = 0;
    long long total_stardust = 0;  

    for (int i = 0; i < N; i++) {
        int act;
        cin >> act;

        if (act == 0) {
            stress -= R;
            if (stress < 0) stress = 0;
            combo = 0;
        }
        else {
            int idx = act - 1;
            stress += p[idx];
            if (stress > 100) {
                cout << -1 << '\n';
                return 0;
            }
            long long combo_bonus = 100 + combo * C;
            long long skill_bonus = 100 + skill[idx] * s[idx];
            long long delta_stardust = floor((base[idx] * combo_bonus * skill_bonus) / 10000.0);
            total_stardust += delta_stardust;
            combo++;
            skill[idx]++;
        }
    }

    cout << total_stardust << '\n';

    return 0;
}

'[백준] > C++' 카테고리의 다른 글

백준 10703번 유성 [C++]  (0) 2024.07.11
백준 1456번 거의 소수 [C++]  (0) 2024.07.08
백준 1213번 펠린드롬 만들기 [C++]  (0) 2024.07.05
백준 31718번 Double Up [C++]  (0) 2024.07.04
백준 15831번 준표의 조약돌[C++]  (0) 2024.07.01

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

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>

using namespace std;

int alpha[26];

int main() {
    string s;
    cin >> s;
    int odd = 0;
    char oddChar;

    // 알파벳 개수 세기
    for (char c : s) {
        alpha[c - 'A']++;
    }

    // 홀수 개수 세기
    for (int i = 0; i < 26; i++) {
        if (alpha[i] % 2 != 0) {
            odd++;
            oddChar = i + 'A';
        }
    }

    // 홀수 개수가 1개 이상일 경우 팰린드롬을 만들 수 없음
    if (odd > 1) {
        cout << "I'm Sorry Hansoo" << endl;
        return 0;
    }

    string firstHalf = "";
    string secondHalf = "";

    // 팰린드롬의 첫 번째 절반 생성
    for (int i = 0; i < 26; i++) {
        firstHalf += string(alpha[i] / 2, i + 'A');
    }

    secondHalf = firstHalf;
    reverse(secondHalf.begin(), secondHalf.end());

    // 팰린드롬 만들기
    if (odd == 1) {
        firstHalf += oddChar;
    }

    cout << firstHalf + secondHalf << endl;

    return 0;
}

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

 

 

#문제 해결 방법

 

2를 곱해서 같은수가 된다는거는

2로 계속해서 나눳을때

같은 값이 된다는 소리니..

 

2로 계속 나눠서 같은 값인지 확인해서 개수를 세어주면 된다

 

#전체 코드

 

#include <iostream>
#include <string>
#include <algorithm> 
#include <map>


typedef long long ll;

using namespace std;

int divide(int factor) {
    if (factor % 2 == 1) {
        return factor;
    }
    else {
        return divide(factor / 2);
    }
}

int main() {
    
    int n;
    cin >> n;
    map<int, int> map;
    int freq = 0;
    while (n--) {
        int input;
        cin >> input;
        

        int odd = divide(input);

        if (map.find(odd) == map.end()) {
            map[odd] = 1;
        }
        else {
            map[odd]++;
        }

        freq = max(freq, map[odd]);

    }

    cout << freq<<'\n';

    return 0;
}

 

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

 

 

#문제 간단 정리

 

투 포인터 /슬라이딩 윈도우 문제

 

계속해서 조약돌을 줍다가 검은 조약돌이 초과하게 되면

슬라이딩 윈도우를 줄여주면 된다.

 

 

#문제 해결 방법

 

슬라이딩 윈도우를 사용한다고 생각하고

 

우선 기본적으로 ㅣ , r 두가지의 포인터를 설정하고

 

오른쪽으로 계속 조약돌을 r++ 하면서 주워주되

    while (r < n) {
        bw[color_map[s[r]]]++;
        r++;

 
        while (bw[0] > b ) {
            bw[color_map[s[l]]]--;
            l++;
        }

        if (bw[0] <= b && bw[1] >= w) {
            maxlength = max(maxlength, r - l);
        }
    }

 

만약 검은 조약돌의 개수가 원하는 개수보다 늘어나개 된다면

검은 조약돌이 원하는 개수 이하가 되도록 왼쪽포인터를 l++ 해서

        while (bw[0] > b ) {
            bw[color_map[s[l]]]--;
            l++;
        }

윈도우 사이즈를 줄여주도록 하자

 

 

 

#전체 코드

 

#include <iostream>
#include <string>
#include <algorithm> 
#include <map>

using namespace std;


int main() {
    int n;
    cin >> n;

    int b, w;
    cin >> b >> w;


    string s;
    cin >> s;


    int bw[2] = { 0,0 }; //0은 검정 1은 흰색
    map<char, int>color_map;
    color_map['W'] = 1;
    color_map['B'] = 0;
    int l = 0, r = 0;
    int maxlength = 0;

    while (r < n) {
        bw[color_map[s[r]]]++;
        r++;

 
        while (bw[0] > b ) {
            bw[color_map[s[l]]]--;
            l++;
        }

        if (bw[0] <= b && bw[1] >= w) {
            maxlength = max(maxlength, r - l);
        }
    }

    cout << maxlength << '\n';
    

    return 0;
}

+ Recent posts