19939번: 박 터뜨리기

$N$개의 공을 $K$개의 바구니에 문제의 규칙을 만족하면서 나눠 담을 수 있다면, 가장 많이 담긴 바구니와 가장 적게 담긴 바구니의 공의 개수 차이를 출력한다. 나눠 담을 수 없는 경우에는 -1을

www.acmicpc.net

문제 설명

 K개의 팀이 박 터트리기 게임을 한다. 각 팀은 하나의 바구니를 가지고 있고, 바구니에 들어있는 공을 던져서 자기 팀의 박을 터트려야 한다.

우리는 게임을 준비하기 위해서, N개의 공을 K개의 바구니에 나눠 담아야 한다. 이때, 게임의 재미를 위해서 바구니에 담기는 공의 개수를 모두 다르게 하고 싶다. 즉, N개의 공을 K개의 바구니에 빠짐없이 나누어 담는데, 각 바구니에는 1개 이상의 공이 있어야 하고, 바구니에 담긴 공의 개수가 모두 달라야 한다.

게임의 불공정함을 줄이기 위해서, 가장 많이 담긴 바구니와 가장 적게 담긴 바구니의 공의 개수 차이가 최소가 되도록 담을 것이다.

공을 바구니에 나눠 담기 위한 규칙을 정리하면 다음과 같다.

  1.  N개의 공을 K개의 바구니에 빠짐없이 나누어 담는다.
  2. 각 바구니에는 1개 이상의 공이 들어 있어야 한다.
  3. 각 바구니에 담긴 공의 개수는 모두 달라야 한다.
  4. 가장 많이 담긴 바구니와 가장 적게 담긴 바구니의 공의 개수 차이가 최소가 되어야 한다.

위의 규칙을 모두 만족하며 N개의 공을 K개의 바구니에 나눠 담을 때, 나눠 담을 수 있는지 여부를 결정하고, 담을 수 있는 경우에는 가장 많이 담긴 바구니와 가장 적게 담긴 바구니의 공의 개수 차이를 계산해서 출력하는 프로그램을 작성하시오.

 

입력 

첫 번째 줄에 공의 개수를 나타내는 N과 팀의 수를 나타내는 정수 K가 주어진다.

 

출력

N개의 공을 K개의 바구니에 문제의 규칙을 만족하면서 나눠 담을 수 있다면, 가장 많이 담긴 바구니와 가장 적게 담긴 바구니의 공의 개수 차이를 출력한다. 나눠 담을 수 없는 경우에는 -1을 출력한다.

 

제한

  • 시간 제한 0.25초
  • 메모리 제한 512 MB

풀이

#include <iostream>
using namespace std;
int main()
{
    int n, k;
    cin >> n >> k;
    int ans = 0;
    int nn[1001];
    for (int i = 1; i <= k; i++)
    {
        ans += i;
    }
    n -= ans;
    if (n < 0)
    {
        cout<<"-1";
    }
    else
    {
        nn[0] = n / k;
        n -= (n / k) * k;
        for (int i = 1; i <= k; i++)
        {
            nn[i] = nn[i - 1] + 1;
        }
        if(n != 0)
            nn[k]++;
        cout << nn[k] - nn[1];
    }
}

1부터 K까지 최소로 공을 넣게 되는 경우 몇개의 공이 필요한지 먼저 계산을 했다.

 

이때 N의 값을 초과한다면 -1을 출력하고 그렇지 않은 경우 그만큼 N의 값에서 빼서 남은 공의 수를 계산했다.

 

K개의 바구니에 공을 하나씩 넣게되면 전체 공의 수가 K만큼 감소하게 된다.

 

이를 이용해서 남은 공에서 K만큼 나누게 되면 전체 바구니에 K만큼 공이 들어가게 되고 그 값이 첫번째 바구니에 들어가야할 공의 수가 된다.

 

나누어 떨어지지 않는 경우 남은 공의 수를 계산해서 바구니에 넣어주어야 한다.

 

바구니의 뒤에서부터 공을 하나씩 넣어주면 모두 다른 수의 공을 넣을 수 있고 남은 공도 처리할 수 있다.

 

마지막 바구니의 값만 있으면 되기 때문에 마지막 갑만 증가시키고 값의 차이를 계산해 출력한다.

'Backjoon' 카테고리의 다른 글

[BOJ][C++] 1925 - 삼각형  (0) 2023.01.19
[BOJ][C++] 2638 - 치즈  (0) 2022.12.20
[BOJ][C++] 3987 - 보이저 1호  (0) 2022.10.14
[BOJ][C++] 1477 - 휴게소 세우기  (1) 2022.10.13
[BOJ][C++] 1303 - 전쟁 - 전투  (0) 2022.10.06
 

1925번: 삼각형

평면상에 세 개의 점이 주어지면, 그 세 점으로 이루어지는 삼각형은 유일하게 결정된다. 또는, 삼각형이 이루어지지 않기도 한다. 세 점의 좌표가 주어졌을 때 다음에 따라 이 삼각형의 종류를

www.acmicpc.net

문제 설명

평면상에 세 개의 점이 주어지면, 그 세 점으로 이루어지는 삼각형은 유일하게 결정된다. 또는, 삼각형이 이루어지지 않기도 한다. 세 점의 좌표가 주어졌을 때 다음에 따라 이 삼각형의 종류를 판단하는 프로그램을 작성하시오.

  1. 세 점이 일직선 위에 있으면 - ‘삼각형이 아님’  출력할 때는 X
  2. 세 변의 길이가 같으면 - ‘정삼각형’ 출력할 때는 JungTriangle
  3. 두 변의 길이가 같으면
    1. 가장 큰 각이 90°보다 크면 - ‘둔각이등변삼각형’ 출력할 때는 Dunkak2Triangle
    2. 가장 큰 각이 90°이면 - ‘직각이등변삼각형’ 출력할 때는 Jikkak2Triangle
    3. 가장 큰 각이 90°보다 작으면 - ‘예각이등변삼각형’ 출력할 때는 Yeahkak2Triangle
  4. 세 변의 길이가 모두 다르면
    1. 가장 큰 각이 90°보다 크면 - ‘둔각삼각형’ 출혁할 때는 DunkakTriangle
    2. 가장 큰 각이 90°이면 - ‘직각삼각형’ 출력할 때는 JikkakTriangle
    3. 가장 큰 각이 90°보다 작으면 - ‘예각삼각형’ 출력할 때는 YeahkakTriangle

입력 

첫째 줄부터 셋째 줄까지 삼각형을 이루는 점의 x좌표와 y좌표가 빈칸을 사이에 두고 주어진다. 입력되는 수는 절댓값이 10,000을 넘지 않는 정수이다. 입력으로 주어지는 세 좌표는 중복되지 않는다.

 

출력

위의 경우에 따라 삼각형의 종류가 무엇인지 출력한다.

 

제한

  • 시간 제한 2초
  • 메모리 제한 128 MB

풀이

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    int x1, x2, x3;
    int y1, y2, y3;
    cin >> x1 >> y1;
    cin >> x2 >> y2;
    cin >> x3 >> y3;
    if ((y1 - y2) * (x1 - x3) == (x1 - x2) * (y1 - y3))
    {
        cout << "X";
    }
    else
    {
        int d[3];
        d[0] = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
        d[1] = (x3 - x2) * (x3 - x2) + (y3 - y2) * (y3 - y2);
        d[2] = (x1 - x3) * (x1 - x3) + (y1 - y3) * (y1 - y3);
        sort(d, d + 3);
        if (d[0] == d[1] && d[1] == d[2])
        {
            cout << "JungTriangle";
        }
        else if (d[0] == d[1] || d[1] == d[2])
        {
            if (d[2] == d[0] + d[1])
                cout << "Jikkak2Triangle";
            else if (d[2] < d[0] + d[1])
                cout << "Yeahkak2Triangle";
            else
                cout << "Dunkak2Triangle";
        }
        else
        {
            if (d[2] == d[0] + d[1])
                cout << "JikkakTriangle";
            else if (d[2] < d[0] + d[1])
                cout << "YeahkakTriangle";
            else
                cout << "DunkakTriangle";
        }
    }
}

점 3개를 이용해 어떤 삼각형인지 확인하는 문제이다.

 

1개의 점과 나머지 2개의 점의 기울기가 같다면 세 점은 일직선위에 있는 점으로 삼각형이 아니게 된다.

 

기울기는 y증가량 / x증가량으로 구하게 되는데 증가량이 0인경우 0으로 나누는 문제가 발생한다.

 

이를 식으로 나타내면 y1-y2 / x1-x2 == y1-y3 / x1-x3 가 되는데 식을 약간 변형하여 y1-y2 * x1-x3 == y1-y3 * x1-x2로 만들 수 있다.

 

피타고라스의 정리에 따라 각 변이 a,b,c라고 했을때

 

a*a + b*b == c*c 의 경우 직각 삼각형,

a*a + b*b < c*c 의 경우  둔각 삼각형,

a*a + b*b > c*c 의 경우 예각 삼각형임을 알 수 있다.

'Backjoon' 카테고리의 다른 글

[BOJ][C++] 19939 - 박 터뜨리기  (0) 2023.01.26
[BOJ][C++] 2638 - 치즈  (0) 2022.12.20
[BOJ][C++] 3987 - 보이저 1호  (0) 2022.10.14
[BOJ][C++] 1477 - 휴게소 세우기  (1) 2022.10.13
[BOJ][C++] 1303 - 전쟁 - 전투  (0) 2022.10.06
 

2638번: 치즈

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5 ≤ N, M ≤ 100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로

www.acmicpc.net

문제 설명

N×M의 모눈종이 위에 아주 얇은 치즈가 <그림 1>과 같이 표시되어 있다. 단, N 은 세로 격자의 수이고, M 은 가로 격자의 수이다. 이 치즈는 냉동 보관을 해야만 하는데 실내온도에 내어놓으면 공기와 접촉하여 천천히 녹는다. 그런데 이러한 모눈종이 모양의 치즈에서 각 치즈 격자(작 은 정사각형 모양)의 4변 중에서 적어도 2변 이상이 실내온도의 공기와 접촉한 것은 정확히 한시간만에 녹아 없어져 버린다. 따라서 아래 <그림 1> 모양과 같은 치즈(회색으로 표시된 부분)라면 C로 표시된 모든 치즈 격자는 한 시간 후에 사라진다.

<그림 1>

<그림 2>와 같이 치즈 내부에 있는 공간은 치즈 외부 공기와 접촉하지 않는 것으로 가정한다. 그러므 로 이 공간에 접촉한 치즈 격자는 녹지 않고 C로 표시된 치즈 격자만 사라진다. 그러나 한 시간 후, 이 공간으로 외부공기가 유입되면 <그림 3>에서와 같이 C로 표시된 치즈 격자들이 사라지게 된다.

<그림 2>

<그림 3>

모눈종이의 맨 가장자리에는 치즈가 놓이지 않는 것으로 가정한다. 입력으로 주어진 치즈가 모두 녹아 없어지는데 걸리는 정확한 시간을 구하는 프로그램을 작성하시오.

 

입력 

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5 ≤ N, M ≤ 100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로 표시된다. 또한, 각 0과 1은 하나의 공백으로 분리되어 있다.

 

출력

출력으로는 주어진 치즈가 모두 녹아 없어지는데 걸리는 정확한 시간을 정수로 첫 줄에 출력한다.

 

제한

  • 시간 제한 1초
  • 메모리 제한 128 MB

풀이

#include <iostream>
#include <queue>
using namespace std;
int nm[101][101];
int ch[101][101];
bool b[101][101];
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            cin >> nm[i][j];
        }
    }
    int ans = 0;
    while (true)
    {
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                ch[i][j] = 0;
                b[i][j] = 0;
            }
        }
        queue<pair<int, int>> q;
        q.push({0, 0});
        b[0][0] = true;
        while (!q.empty())
        {
            int x = q.front().first;
            int y = q.front().second;
            q.pop();
            for (int i = 0; i < 4; i++)
            {
                if (x + dx[i] < n && x + dx[i] >= 0 && y + dy[i] < m && y + dy[i] >= 0)
                {
                    if (b[x + dx[i]][y + dy[i]])
                        continue;
                    if (nm[x + dx[i]][y + dy[i]] == 1)
                    {
                        ch[x + dx[i]][y + dy[i]]++;
                    }
                    else
                    {
                        b[x + dx[i]][y + dy[i]] = true;
                        q.push({x + dx[i], y + dy[i]});
                    }
                }
            }
        }
        bool bans = false;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if (ch[i][j] >= 2)
                {
                    nm[i][j] = 0;
                    bans = true;
                }
            }
        }
        if (bans)
            ans++;
        else
            break;
    }
    cout << ans;
}

빈 공간을 bfs를 통해 탐색 하게되면 중간에 빈 공간은 무시하고 바깥쪽 빈공간에 닿는 치즈만 확인 할 수 있다.

 

빈 공간 주변에 치즈가 있으면 그 칸의 값을 증가시켜 탐색이 끝나고 난 후 2개 이상의 빈공간이 있는 치즈를 제거한다.

 

치즈를 제거하게 되면 ans값을 증가시키고 그렇지 않는 경우 그대로 종료한다.

'Backjoon' 카테고리의 다른 글

[BOJ][C++] 19939 - 박 터뜨리기  (0) 2023.01.26
[BOJ][C++] 1925 - 삼각형  (0) 2023.01.19
[BOJ][C++] 3987 - 보이저 1호  (0) 2022.10.14
[BOJ][C++] 1477 - 휴게소 세우기  (1) 2022.10.13
[BOJ][C++] 1303 - 전쟁 - 전투  (0) 2022.10.06
 

3987번: 보이저 1호

첫째 줄에 시그널을 보내는 방향을 출력한다. (U: 위, R: 오른쪽, D: 아래, L: 왼쪽) 만약, 방향이 여러 가지가 존재한다면, U, R, D, L의 순서 중 앞서는 것을 출력한다. 둘째 줄에는 가장 긴 시간을 출

www.acmicpc.net

문제 설명

보이저 1호는 1977년에 발사된 NASA의 태양계 무인 탐사선이다. 현재 보이저 1호는 태양권덮개 (헬리오시스)에 있다.

보이저 1호와 같이 오랜 기간동안 활동하는 탐사선은 경로를 항성계를 만날 때 마다 라디오 시그널 메시지를 이용해서 기록하고 있다.

항성계를 N * M개의 직사각형으로 나누어져 있는 N행 M열의 직사각형 그리드라고 생각해보자. 각 칸은 행성, 블랙홀을 포함할 수 있으며, 비어있을 수도 있다. 탐사선은 인접한 네 칸(위, 아래, 오른쪽, 왼쪽)중에서 하나를 골라서 시그널을 보낸다.

시그널은 항상 일직선으로 전파되며, 행성을 만났을 경우에는 전파되는 방향이 90도로 바뀌게 된다. 행성은 '/'와 '\'로 표현되는 두 종류가 있으며, 반사되는 법칙은 아래 그림과 같다.

시그널이 블랙홀이 있는 칸을 만나거나 항성계를 벗어날 때 까지 계속 전파된다. 시그널이 인접한 칸으로 이동하는데 걸리는 시간은 1초이다.

탐사선이 어느 방향으로 시그널을 보내면, 시그널이 항성계 내부에 있는 시간이 최대가 되는지 구하는 프로그램을 작성하시오.

 

입력 

첫째 줄에 N과 M이 주어진다. (1 ≤ N, M ≤ 500)

다음 N개 줄에는 M개의 문자가 주어지며, '/'와 '\'는 행성을, C는 블랙홀을, '.'는 빈 칸을 나타낸다.

마지막 줄에는 탐사선이 있는 위치 PR과 PC가 주어진다. (1 ≤ PR ≤ N, 1 ≤ PC ≤ M)

 

출력

첫째 줄에 시그널을 보내는 방향을 출력한다. (U: 위, R: 오른쪽, D: 아래, L: 왼쪽)

만약, 방향이 여러 가지가 존재한다면, U, R, D, L의 순서 중 앞서는 것을 출력한다.

둘째 줄에는 가장 긴 시간을 출력한다. 만약, 시그널이 항성계 내에서 무한히 전파될 수 있다면 "Voyager"를 출력한다.

 

제한

  • 시간 제한 1초
  • 메모리 제한 128 MB

풀이

#include <iostream>
using namespace std;
int n, m;
char nm[501][501];
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
char dc[4] = {'U','R','D','L'};
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        string s;
        cin >> s;
        for (int j = 1; j <= m; j++)
        {
            nm[i][j] = s[j - 1];
        }
    }
    int x, y;
    cin >> x >> y;
    string ansc = "U";
    int anst = 0;
    for (int q = 0; q < 4; q++)
    {
        int time = 0;
        int tx = x;
        int ty = y;
        int b = q;
        while (true)
        {
            time++;
            if (tx + dx[b] <= n && tx + dx[b] > 0 && ty + dy[b] <= m && ty + dy[b] > 0)
            {
                tx+=dx[b];
                ty+=dy[b];
                if(tx == x && ty == y && b == q)
                {
                    time = 987654321;
                    break;
                }
                if (nm[tx][ty] == 'C')
                    break;
                else if (nm[tx][ty] == '\\')
                {
                    if (b == 0)
                        b = 3;
                    else if (b == 1)
                        b = 2;
                    else if (b == 2)
                        b = 1;
                    else
                        b = 0;
                }
                else if (nm[tx][ty] == '/')
                {
                    if (b == 0)
                        b = 1;
                    else if (b == 1)
                        b = 0;
                    else if (b == 2)
                        b = 3;
                    else
                        b = 2;
                }
            }
            else
                break;
        }
        if(time>anst)
        {
            ansc = dc[q];
            anst = time;
        }
    }
    cout<<ansc<<endl;
    if(anst == 987654321)
        cout<<"Voyager";
    else
        cout<<anst;
}

 

간단한 구현 문제이다.

 

조건에 맞게끔 프로그램이 동작하도록 만들고 순환하는 조건을 잘 찾아주면 된다.

 

탐사선의 위치를 출발한 방향과 동일하게 지나게되는 경우 순환하는 것으로 순환을 찾았다.

'Backjoon' 카테고리의 다른 글

[BOJ][C++] 1925 - 삼각형  (0) 2023.01.19
[BOJ][C++] 2638 - 치즈  (0) 2022.12.20
[BOJ][C++] 1477 - 휴게소 세우기  (1) 2022.10.13
[BOJ][C++] 1303 - 전쟁 - 전투  (0) 2022.10.06
[BOJ][C++] 1069 - 집으로  (0) 2022.09.28
 

1477번: 휴게소 세우기

첫째 줄에 현재 휴게소의 개수 N, 더 지으려고 하는 휴게소의 개수 M, 고속도로의 길이 L이 주어진다. 둘째 줄에 현재 휴게소의 위치가 공백을 사이에 두고 주어진다.

www.acmicpc.net

문제 설명

다솜이는 유료 고속도로를 가지고 있다. 다솜이는 현재 고속도로에 휴게소를 N개 가지고 있는데, 휴게소의 위치는 고속도로의 시작으로부터 얼만큼 떨어져 있는지로 주어진다. 다솜이는 지금 휴게소를 M개 더 세우려고 한다.

다솜이는 이미 휴게소가 있는 곳에 휴게소를 또 세울 수 없고, 고속도로의 끝에도 휴게소를 세울 수 없다. 휴게소는 정수 위치에만 세울 수 있다.

다솜이는 이 고속도로를 이용할 때, 모든 휴게소를 방문한다. 다솜이는 휴게소를 M개 더 지어서 휴게소가 없는 구간의 길이의 최댓값을 최소로 하려고 한다. (반드시 M개를 모두 지어야 한다.)

예를 들어, 고속도로의 길이가 1000이고, 현재 휴게소가 {200, 701, 800}에 있고, 휴게소를 1개 더 세우려고 한다고 해보자.

일단, 지금 이 고속도로를 타고 달릴 때, 휴게소가 없는 구간의 최댓값은 200~701구간인 501이다. 하지만, 새로운 휴게소를 451구간에 짓게 되면, 최대가 251이 되어서 최소가 된다.

 

입력 

첫째 줄에 현재 휴게소의 개수 N, 더 지으려고 하는 휴게소의 개수 M, 고속도로의 길이 L이 주어진다. 둘째 줄에 현재 휴게소의 위치가 공백을 사이에 두고 주어진다.

 

출력

첫째 줄에 M개의 휴게소를 짓고 난 후에 휴게소가 없는 구간의 최댓값의 최솟값을 출력한다.

 

제한

  • 시간 제한 2초
  • 메모리 제한 128 MB
  • 0 ≤ N ≤ 50
  • 1 ≤ M ≤ 100
  • 100 ≤ L ≤ 1,000
  • 1 ≤ 휴게소의 위치 ≤ L-1
  • N+M < L
  • 모든 휴게소의 위치는 중복되지 않음
  • 입력으로 주어지는 모든 수는 정수

풀이

#include <iostream>
using namespace std;
int n, m, l;
int nn[51];
int main()
{
    cin >> n >> m >> l;
    for (int i = 0; i < n; i++)
    {
        cin >> nn[i];
    }
    int a = 1;
    int b = 1000;
    while (a <= b)
    {
        int c = (a + b) / 2;
        bool temp[1001];
        fill(temp, temp + 1001, false);
        for (int i = 0; i < n; i++)
        {
            temp[nn[i]] = true;
        }
        int d = 0;
        int tm = 0;
        for (int i = 0; i < l; i++)
        {
            if (temp[i])
            {
                d = i;
            }
            else if (i - d == c)
            {
                d = i;
                temp[i] = true;
                tm++;
            }
        }
        if (tm <= m)
        {
            b = c - 1;
        }
        else
        {
            a = c + 1;
        }
    }
    cout << a;
}

 

이분탐색을 통해 기존의 휴게소부터 얼마나 떨어진 곳에 휴게소를 놓을지 찾는 문제이다.

 

휴게소를 저장할 배열 temp를 만들고 d라는 변수를 통해 휴게소의 위치를 저장했다.

 

휴게소를 만나면 d값을 다시 지정하고 d로부터 떨어진 거리가 c만큼 되면 휴게소를 지었다고 생각하고 tm값을 증가시킨다.

 

tm의 값이 문제에서 주어진 m값보다 작거나 같을경우 거리를 더 좁게해서 휴게소를 지어야한다는 뜻이 된다.

 

최소거리를 출력한다.

'Backjoon' 카테고리의 다른 글

[BOJ][C++] 2638 - 치즈  (0) 2022.12.20
[BOJ][C++] 3987 - 보이저 1호  (0) 2022.10.14
[BOJ][C++] 1303 - 전쟁 - 전투  (0) 2022.10.06
[BOJ][C++] 1069 - 집으로  (0) 2022.09.28
[BOJ][C++] 16931 - 겉넓이 구하기  (1) 2022.09.22
 

1303번: 전쟁 - 전투

첫째 줄에는 전쟁터의 가로 크기 N, 세로 크기 M(1 ≤ N, M ≤ 100)이 주어진다. 그 다음 두 번째 줄에서 M+1번째 줄에는 각각 (X, Y)에 있는 병사들의 옷색이 띄어쓰기 없이 주어진다. 모든 자리에는

www.acmicpc.net

문제 설명

전쟁은 어느덧 전면전이 시작되었다. 결국 전투는 난전이 되었고, 우리 병사와 적국 병사가 섞여 싸우게 되었다. 그러나 당신의 병사들은 흰색 옷을 입고, 적국의 병사들은 파란색 옷을 입었기 때문에 서로가 적인지 아군인지는 구분할 수 있다. 문제는 같은 팀의 병사들은 모이면 모일수록 강해진다는 사실이다.

N명이 뭉쳐있을 때는 N2의 위력을 낼 수 있다. 과연 지금 난전의 상황에서는 누가 승리할 것인가? 단, 같은 팀의 병사들이 대각선으로만 인접한 경우는 뭉쳐 있다고 보지 않는다.

 

입력 

첫째 줄에는 전쟁터의 가로 크기 N, 세로 크기 M(1 ≤ N, M ≤ 100)이 주어진다. 그 다음 두 번째 줄에서 M+1번째 줄에는 각각 (X, Y)에 있는 병사들의 옷색이 띄어쓰기 없이 주어진다. 모든 자리에는 병사가 한 명 있다. B는 파란색, W는 흰색이다. 당신의 병사와 적국의 병사는 한 명 이상 존재한다.

 

출력

첫 번째 줄에 당신의 병사의 위력의 합과 적국의 병사의 위력의 합을 출력한다.

 

제한

  • 시간 제한 2초
  • 메모리 제한 128 MB

풀이

#include <iostream>
using namespace std;
char nm[101][101];
bool nmb[101][101];
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
int n, m;
int f(int a, int b, char c)
{
    int t = 1;
    for (int i = 0; i < 4; i++)
    {
        if (a + dx[i] < m && a + dx[i] >= 0 && b + dy[i] < n && b + dy[i] >= 0)
        {
            if (nm[a + dx[i]][b + dy[i]] == c && !nmb[a + dx[i]][b + dy[i]])
            {
                nmb[a + dx[i]][b + dy[i]] = true;
                t += f(a + dx[i], b + dy[i], c);
            }
        }
    }
    return t;
}
int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        string s;
        cin >> s;
        for (int j = 0; j < s.length(); j++)
        {
            nm[i][j] = s[j];
        }
    }
    long long int ansb = 0;
    long long int answ = 0;
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (!nmb[i][j])
            {
                nmb[i][j] = true;
                long long int temp = f(i, j, nm[i][j]);
                temp *= temp;
                if (nm[i][j] == 'B')
                    ansb += temp;
                else
                    answ += temp;
            }
        }
    }
    cout << answ << " " << ansb;
}

 

2중 for문을 돌면서 상하좌우가 인접한 병사의 수를 계산해서 제곱해서 더해주면 된다.

 

방문을 담당할 배열은 nmb배열이다.

 

dfs의 방식을 따라서 해봤다.

 

n이 가로라는 사항을 주의해서 봐야한다.

'Backjoon' 카테고리의 다른 글

[BOJ][C++] 3987 - 보이저 1호  (0) 2022.10.14
[BOJ][C++] 1477 - 휴게소 세우기  (1) 2022.10.13
[BOJ][C++] 1069 - 집으로  (0) 2022.09.28
[BOJ][C++] 16931 - 겉넓이 구하기  (1) 2022.09.22
[BOJ][C++] 1358 - 하키  (0) 2022.09.17
 

1069번: 집으로

은진이는 지금 (X, Y)에 있고, (0, 0)에 있는 집으로 가능한 빨리 가려고 한다. 이동할 수 있는 방법은 다음 두 가지이다. 첫 번째 방법은 걷는것이다. 걸을 때는 1초에 1만큼 움직인다. 두 번째 방법

www.acmicpc.net

문제 설명

은진이는 지금 (X, Y)에 있고, (0, 0)에 있는 집으로 가능한 빨리 가려고 한다. 이동할 수 있는 방법은 다음 두 가지이다.

첫 번째 방법은 걷는것이다. 걸을 때는 1초에 1만큼 움직인다. 두 번째 방법은 점프하는 것이다. 점프를 하게 되면, T초에 D만큼 움직인다. 점프는 일직선으로만 할 수 있고, 정확하게 D칸만 움직일 수 있다.

위의 두 가지 방법을 이용해서 집에 돌아오는데 걸리는 시간의 최솟값을 구하는 프로그램을 작성하시오. 꼭 한 가지 방법만 사용해야 되는것이 아니고, 두 가지 방법을 적절히 조합해서 가장 빠른 시간을 구하는 것이다.

 

입력 

첫째 줄에 네 정수 X, Y, D, T가 주어진다.

 

출력

첫째 줄에 집에 돌아오는데 걸리는 시간의 최솟값을 출력한다. 절대/상대 오차는 10-9까지 허용한다.

 

제한

  • 시간 제한 2초
  • 메모리 제한 128 MB

풀이

#include <iostream>
#include <cmath>
using namespace std;
double min(double a, double b)
{
    return a < b ? a : b;
}
int main()
{
    double x, y, d, t;
    cin >> x >> y >> d >> t;
    double di = sqrt(x * x + y * y);
    double ans = di;
    int jump = di / d;
    di -= jump * d;
    if (jump == 0)
        ans = min(ans, min(t * 2, d - di + t));
    else
        ans = min(ans,min(jump*t+di,(jump+1)*t));
    cout<<fixed;
    cout.precision(9);
    cout<<ans;
}

 

여러가지 경우에 대해서 어떤 경우가 가장 짧은 시간을 가지는지 구하면 된다.

 

1. 걸어서 이동하는 경우

2. 거리가 점프거리보다 작을때

3. 점프하고 남은거리를 걸어서 이동하는 경우

4. 점프만 하고 이동하는 경우

 

1번의 경우 원점과 거리를 계산하면 된다.

 

2번의 경우 점프하고 넘어간 거리만큼 걸어서 가는 경우이다.

 

3번의 경우 원점과 가까이 점프하고 남은거리를 걸어는 경우이다.

 

4번의 경우 거리가 점프거리보다 작을때 2번 점프해서 도착하거나 최대한 가까이 점프한 후에 한번더 점프를 통해 원점으로 도달하는 경우 이다.

 

점프는 직선으로 해야하지만 방향은 상관이 없기 때문에 시작점에서 원점+d까지의 거리까지 점프하고 거기서 원점으로 점프하면 두번으로 원점에 도착할 수 있다.

 

최소값을 출력한다.

'Backjoon' 카테고리의 다른 글

[BOJ][C++] 1477 - 휴게소 세우기  (1) 2022.10.13
[BOJ][C++] 1303 - 전쟁 - 전투  (0) 2022.10.06
[BOJ][C++] 16931 - 겉넓이 구하기  (1) 2022.09.22
[BOJ][C++] 1358 - 하키  (0) 2022.09.17
[BOJ][C++] 2458 - 키 순서  (0) 2022.09.15
 

16931번: 겉넓이 구하기

크기가 N×M인 종이가 있고, 종이는 1×1크기의 칸으로 나누어져 있다. 이 종이의 각 칸 위에 1×1×1 크기의 정육면체를 놓아 3차원 도형을 만들었다. 종이의 각 칸에 놓인 정육면체의 개수가 주어

www.acmicpc.net

문제 설명

크기가 N×M인 종이가 있고, 종이는 1×1크기의 칸으로 나누어져 있다. 이 종이의 각 칸 위에 1×1×1 크기의 정육면체를 놓아 3차원 도형을 만들었다.

종이의 각 칸에 놓인 정육면체의 개수가 주어졌을 때, 이 도형의 겉넓이를 구하는 프로그램을 작성하시오.

위의 그림은 3×3 크기의 종이 위에 정육면체를 놓은 것이고, 겉넓이는 60이다.

 

입력 

첫째 줄에 종이의 크기 N, M이 주어진다. 둘째 줄부터 N개의 줄에는 종이의 각 칸에 놓인 정육면체의 수가 주어진다.

 

출력

첫째 줄에 도형의 겉넓이를 출력한다.

 

제한

  • 시간 제한 1초
  • 메모리 제한 512MB

풀이

#include <iostream>
using namespace std;
int nm[105][105];
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            cin >> nm[i][j];
        }
    }
    int ans = n * m * 2;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            if (nm[i - 1][j] < nm[i][j])
                ans += nm[i][j] - nm[i - 1][j];
            if (nm[i + 1][j] < nm[i][j])
                ans += nm[i][j] - nm[i + 1][j];
            if (nm[i][j + 1] < nm[i][j])
                ans += nm[i][j] - nm[i][j + 1];
            if (nm[i][j - 1] < nm[i][j])
                ans += nm[i][j] - nm[i][j - 1];
        }
    }
    cout << ans;
}

 

2차원 배열 각각의 위치에서 정육면체의 면이 얼마나 공개되어있는지를 찾아서 모두 더해주면 되는 문제이다.

 

위쪽면과 아래쪽면은 항상 n*m의 크기를 가지므로 ans의 값에 바로 더해주었다.

 

정육면체의 4면은 i+1, i-1, j+1, j-1의 값이 자신이 가지는 값보다 작을경우 그 차이만큼 면적이 공개되어 있는 것이다.

 

배열을 만들고 0부터 입력받는것이 아닌 1부터 입력을 시작해 바깥쪽 부분의 계산을 쉽게 해주었다.

'Backjoon' 카테고리의 다른 글

[BOJ][C++] 1303 - 전쟁 - 전투  (0) 2022.10.06
[BOJ][C++] 1069 - 집으로  (0) 2022.09.28
[BOJ][C++] 1358 - 하키  (0) 2022.09.17
[BOJ][C++] 2458 - 키 순서  (0) 2022.09.15
[BOJ][C++] 21608 - 상어 초등학교  (0) 2022.09.13
 

1358번: 하키

첫째 줄에 수 W H X Y P가 주어진다. P는 선수의 수이다. W와 H는 100보다 작거나 같은 자연수이고, H는 짝수이다. X와 Y는 절댓값이 100보다 작거나 같은 정수이다. P는 최대 50인 자연수이다. 둘째 줄부

www.acmicpc.net

문제 설명

지난주에, 민식주식회사는 IIHF(International Ice Hockey Federation)로부터 긴급한 전화를 받았다.

IIHF는 같은 팀이 링크안에 너무 많으면 알람이 울리는 시스템을 설치해달라고 요청했다. 시스템은 다음과 같이 3개의 부분으로 이루어진다.

  1. 디지털카메라가 링크의 사진을 매 1초마다 찍는다.
  2. 디지털카메라가 찍은 사진에서 각 선수의 위치를 뽑아낸다.
  3. 하키 링크 안에 같은 팀 선수가 총 몇 명인지 계산한다.

하키 링크는 (X, Y)가 가장 왼쪽 아래 모서리인 W * H 크기의 직사각형과, 반지름이 H/2이면서 중심이 (X, Y+R), (X+W, Y+R)에 있는 두 개의 원으로 이루어져 있다. 아래 그림을 참고한다.

선수들의 위치가 주어질 때, 링크 안 또는 경계에 있는 선수가 총 몇 명인지 구하는 프로그램을 작성하시오.

입력 

첫째 줄에 수 W H X Y P가 주어진다. P는 선수의 수이다. W와 H는 100보다 작거나 같은 자연수이고, H는 짝수이다. X와 Y는 절댓값이 100보다 작거나 같은 정수이다. P는 최대 50인 자연수이다. 둘째 줄부터 P개의 줄에 각 선수들의 x좌표와 y좌표가 주어진다. 이 좌표는 절댓값이 300보다 작거나 같은 정수이다.

 

출력

첫째 줄에 링크 안에 있는 선수의 수를 출력한다.

 

제한

  • 시간 제한 2초
  • 메모리 제한 128 MB

풀이

#include <iostream>
using namespace std;
int main()
{
    int w, h, x, y, p;
    cin >> w >> h >> x >> y >> p;
    int ans = 0;
    for (int i = 0; i < p; i++)
    {
        int a, b;
        cin >> a >> b;
        if (a >= x && b >= y && a <= x + w && b <= y + h)
            ans++;
        else if ((a - x) * (a - x) + (b - (y + h / 2)) * (b - (y + h / 2)) <= (h / 2) * (h / 2))
            ans++;
        else if ((a - (x + w)) * (a - (x + w)) + (b - (y + h / 2)) * (b - (y + h / 2)) <= (h / 2) * (h / 2))
            ans++;
    }
    cout << ans;
}

입력되는 좌표가 직사각형 내부에 있는지 원의 내부에 있는지 확인해서 ans값을 증가시킨다

 

원의 내부에 있는지 확인하기 위해 원의 중심과 선수의 거리를 계산해서 반지름보다 크면 원 밖에 있는 것이고 아니면 원 내부에 있는 것이다.

'Backjoon' 카테고리의 다른 글

[BOJ][C++] 1069 - 집으로  (0) 2022.09.28
[BOJ][C++] 16931 - 겉넓이 구하기  (1) 2022.09.22
[BOJ][C++] 2458 - 키 순서  (0) 2022.09.15
[BOJ][C++] 21608 - 상어 초등학교  (0) 2022.09.13
[BOJ][C++] 10942 - 팰린드롬?  (0) 2022.09.05
 

2458번: 키 순서

1번부터 N번까지 번호가 붙여져 있는 학생들에 대하여 두 학생끼리 키를 비교한 결과의 일부가 주어져 있다. 단, N명의 학생들의 키는 모두 다르다고 가정한다. 예를 들어, 6명의 학생들에 대하여

www.acmicpc.net

문제 설명

1번부터 N번까지 번호가 붙여져 있는 학생들에 대하여 두 학생끼리 키를 비교한 결과의 일부가 주어져 있다. 단, N명의 학생들의 키는 모두 다르다고 가정한다. 예를 들어, 6명의 학생들에 대하여 6번만 키를 비교하였고, 그 결과가 다음과 같다고 하자.

  • 1번 학생의 키 < 5번 학생의 키
  • 3번 학생의 키 < 4번 학생의 키
  • 5번 학생의 키 < 4번 학생의 키
  • 4번 학생의 키 < 2번 학생의 키
  • 4번 학생의 키 < 6번 학생의 키
  • 5번 학생의 키 < 2번 학생의 키

이 비교 결과로부터 모든 학생 중에서 키가 가장 작은 학생부터 자신이 몇 번째인지 알 수 있는 학생들도 있고 그렇지 못한 학생들도 있다는 사실을 아래처럼 그림을 그려 쉽게 확인할 수 있다. a번 학생의 키가 b번 학생의 키보다 작다면, a에서 b로 화살표를 그려서 표현하였다. 

1번은 5번보다 키가 작고, 5번은 4번보다 작기 때문에, 1번은 4번보다 작게 된다. 그러면 1번, 3번, 5번은 모두 4번보다 작게 된다. 또한 4번은 2번과 6번보다 작기 때문에, 4번 학생은 자기보다 작은 학생이 3명이 있고, 자기보다 큰 학생이 2명이 있게 되어 자신의 키가 몇 번째인지 정확히 알 수 있다. 그러나 4번을 제외한 학생들은 자신의 키가 몇 번째인지 알 수 없다. 

학생들의 키를 비교한 결과가 주어질 때, 자신의 키가 몇 번째인지 알 수 있는 학생들이 모두 몇 명인지 계산하여 출력하는 프로그램을 작성하시오.

 

입력 

첫째 줄에 학생들의 수 N (2 ≤ N ≤ 500)과 두 학생 키를 비교한 횟수 M (0 ≤ M ≤ N(N-1)/2)이 주어진다. 다음 M개의 각 줄에는 두 학생의 키를 비교한 결과를 나타내는 두 양의 정수 a와 b가 주어진다. 이는 번호가 a인 학생이 번호가 b인 학생보다 키가 작은 것을 의미한다. 

 

출력

자신이 키가 몇 번째인지 알 수 있는 학생이 모두 몇 명인지를 출력한다. 

 

제한

  • 시간 제한 1초
  • 메모리 제한 128 MB

풀이

#include <iostream>
using namespace std;
int n, m;
int nn[501][501];
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            nn[i][j] = 987654321;
        }
    }
    for (int i = 0; i < m; i++)
    {
        int a, b;
        cin >> a >> b;
        nn[a][b] = 1;
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            for (int k = 1; k <= n; k++)
            {
                if (nn[j][k] > nn[j][i] + nn[i][k])
                    nn[j][k] = nn[j][i] + nn[i][k];
            }
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        int temp = 0;
        for (int j = 1; j <= n; j++)
        {
            if (nn[i][j] != 987654321 || nn[j][i] != 987654321)
                temp++;
        }
        if (temp == n - 1)
            ans++;
    }
    cout << ans;
}

최단거리 테이블을 만들고 해당 테이블은 nn[i][j]는 i가 j보다 키가작다는것을 나타낸다.

 

자신보다 키가큰사람이 몇명이고 작은사람이 몇명인지 계산해서 n-1의 값을 가진다면 자신이 몇번째인지 알 수 있다.

'Backjoon' 카테고리의 다른 글

[BOJ][C++] 16931 - 겉넓이 구하기  (1) 2022.09.22
[BOJ][C++] 1358 - 하키  (0) 2022.09.17
[BOJ][C++] 21608 - 상어 초등학교  (0) 2022.09.13
[BOJ][C++] 10942 - 팰린드롬?  (0) 2022.09.05
[BOJ][C++] 2852 - NBA 농구  (0) 2022.08.26

+ Recent posts