이 포스트에서는 프로그래밍 문제 사이트 백준 Online Judge의 Bronze III 난이도에 해당하는 문제들을 풀이할 것입니다.
문제의 난이도가 아주 쉬우므로, 풀이 코드와 함께 간단한 설명만 언급하고 넘어갈 것입니다.
또한 이 포스트에서는 20문제를 풀이할 예정입니다.
2863번 : 이게 분수?
#include <cstdio>
using namespace std;
int main() {
double a, b, c, d, Max = 0;
int i, idx = 0;
scanf("%lf %lf %lf %lf", &a, &b, &c, &d);
for(i=0; i<4; i++) {
if(a/c + b/d > Max) Max = a/c + b/d, idx = i;
int temp = a;
a = c, c = d, d = b, b = temp;
}
printf("%d", idx);
}
문제에서 하라는 대로 표를 만든 뒤 분수 식을 만들고, temp 변수를 이용하여 값들을 한 개씩 옮겨주는 과정을 반복하면서 최댓값을 찾으면 됩니다.
분수 값을 계산해야 하기 때문에 double 자료형을 이용하여 a, b, c, d를 저장하는 것이 좋습니다. (1/20)
14489번 : 치킨 두 마리 (...)
#include <cstdio>
using namespace std;
int main() {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
if(a+b>=c*2) printf("%d", a+b-c*2);
else printf("%d", a+b);
}
두 잔고의 합이 치킨 가격의 2배보다 크거나 같으면 치킨 값을 빼고 잔고의 합을 출력해주면 됩니다.
부등호에 등호를 붙이는 것에 신경을 써야 합니다. (2/20)
6378번 : 디지털 루트
#include <cstdio>
#include <cstring>
using namespace std;
int main() {
while(1) {
int sum = 0;
char num[1005];
scanf("%s", num);
if(!strcmp(num, "0")) break;
for(int i=0; i<strlen(num); i++) sum += num[i]-'0';
while(sum >= 10) {
int temp = sum;
sum = 0;
while(temp) {
sum += temp%10;
temp /= 10;
}
}
printf("%d\n", sum);
}
}
어떤 정수의 각 자릿수를 더해 새로운 수를 만드는 반복 문제입니다.
처음 정수의 입력이 1000자리일지라도, 각 자릿수의 합을 한 번만 구해주면 바로 작은 수가 되어버리기 때문에 첫 입력만 string으로 받아주면 됩니다.
그리고 중간에 디지털 루트를 구하는 과정에서 sum을 temp로 잠시 옮긴 뒤 temp를 분리해주어야 현재 계산하는 수를 보존하면서 계산이 가능합니다. (3/20)
2985번 : 세 수
#include <cstdio>
#include <cstring>
using namespace std;
int main() {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
if(a+b == c) printf("%d+%d=%d", a, b, c);
else if(a == b+c) printf("%d=%d+%d", a, b, c);
else if(a-b == c) printf("%d-%d=%d", a, b, c);
else if(a == b-c) printf("%d=%d-%d", a, b, c);
else if(a*b == c) printf("%d*%d=%d", a, b, c);
else if(a == b*c) printf("%d=%d*%d", a, b, c);
else if(a/b == c) printf("%d/%d=%d", a, b, c);
else if(a == b/c) printf("%d=%d/%d", a, b, c);
}
사칙연산이 성립하는 식을 직접 출력해야 하는 문제입니다.
경우의 수가 8가지밖에 존재하지 않으므로 그냥 전부 검사해주면 됩니다.
다만 나눗셈의 경우 divide by 0 error가 발생할 수 있는데, 정답이 항상 존재하는 경우만 주어진다고 했으므로 나눗셈 조건식을 마지막에 배치해주면 오류가 발생할 일이 사라집니다. (4/20)
2997번 : 네 번째 수
#include <cstdio>
#include <algorithm>
using namespace std;
int main() {
int arr[3];
for(int i=0; i<3; i++) scanf("%d", &arr[i]);
sort(arr, arr+3);
if(arr[1]-arr[0] == arr[2]-arr[1]) printf("%d", arr[2] + (arr[2]-arr[1]));
else if(2*(arr[1]-arr[0]) == arr[2]-arr[1]) printf("%d", arr[1] + (arr[1]-arr[0]));
else if(2*(arr[2]-arr[1]) == arr[1]-arr[0]) printf("%d", arr[0] + (arr[2]-arr[1]));
}
등차수열을 이루는 4개의 수 중 하나가 빠졌을 때 그 숫자를 찾는 문제입니다.
가능한 경우로는 세 개의 수가 등차수열을 이루는 경우와, 2번째로 작은 수가 빠진 경우, 3번째로 작은 수가 빠진 경우인데 이 3가지 경우를 모두 구현해주면 됩니다.
이 때 수를 먼저 오름차순으로 정렬부터 해주고 계산을 해야 합니다.
여기서는 sort 함수를 썼는데, 직접 구현해서 풀어도 별로 오래 걸리지 않습니다.
공차의 경우 인접한 두 수를 빼서 구해주면 됩니다. (5/20)
9517번 : 아이 러브 크로아티아
#include <cstdio>
using namespace std;
int main() {
int N, K, time[105], sum = 0;
char c[105];
scanf("%d %d", &K, &N);
for(int i=0; i<N; i++) scanf("%d %c", &time[i], &c[i]);
for(int i=0; i<N; i++) {
sum += time[i];
if(sum >= 210) break;
else if(c[i] == 'T') {
if(K != 8) K++;
else K = 1;
}
else if(c[i] == 'N' || c[i] == 'P') continue;
}
printf("%d", K);
}
게임 규칙이 쓸데없이 길어서 이해에 시간이 조금 걸릴 수 있겠지만, 요약해보면 대답이 N이나 P일 때는 결국 같은 처리를 해주면 됩니다. (번호의 변경 없이 진행)
그리고 폭탄이 터진다고 해서 즉시 답을 처리하면 입력이 모두 처리되지 않기 때문에, 미리 배열에 입력을 저장하고 저장된 배열을 읽으면서 처리하면 좋습니다. (6/20)
4880번 : 다음수
#include <cstdio>
using namespace std;
int main() {
int a, b, c;
while(1) {
scanf("%d %d %d", &a, &b, &c);
if(!a && !b && !c) break;
else if(a-b == b-c) printf("AP %d\n", c + (c-b));
else printf("GP %d\n", c * (c/b));
}
}
모든 입력이 등차수열 또는 등비수열이라고 하였으므로, 등차수열이 아니면 나머지는 모두 등비수열로 처리해주면 되는 문제입니다.
따라서 공차를 먼저 구해보고 공차가 존재한다면 등차수열로 처리해줍니다. (7/20)
10474번 : 분수 좋아해?
#include <cstdio>
using namespace std;
int main() {
int a, b;
while(1) {
scanf("%d %d", &a, &b);
if(!a && !b) break;
else printf("%d %d / %d\n", a/b, a%b, b);
}
}
분수를 대분수로 나타냈을 때 정수 부분은 분자를 분모로 나눈 몫이 되고, 오른쪽의 분자는 분자를 분모로 나눈 나머지가 됩니다.
그리고 분모는 분모 그대로 출력해주면 됩니다. (8/20)
4493번 : 가위 바위 보?
#include <cstdio>
using namespace std;
int main() {
int T, N, sum1, sum2;
char c1, c2;
scanf("%d", &T);
for(int i=0; i<T; i++) {
sum1 = 0, sum2 = 0;
scanf("%d", &N);
for(int j=0; j<N; j++) {
scanf(" %c %c", &c1, &c2);
if(c1 == 'R' && c2 == 'P') sum2++;
else if(c1 == 'P' && c2 == 'R') sum1++;
else if(c1 == 'P' && c2 == 'S') sum2++;
else if(c1 == 'S' && c2 == 'P') sum1++;
else if(c1 == 'S' && c2 == 'R') sum2++;
else if(c1 == 'R' && c2 == 'S') sum1++;
}
if(sum1 > sum2) printf("Player 1\n");
else if(sum1 < sum2) printf("Player 2\n");
else printf("TIE\n");
}
}
가위바위보 승패 여부를 매 테스트케이스마다 구현해야 하는 약간 귀찮은 문제입니다.
6가지의 경우의 수를 제외하고 나머지 비기는 경우는 어떠한 처리도 하지 않아도 되므로 조건문에서 다루지 않습니다.
R, P, S를 입력받을 때 앞에 널 문자가 %c에 입력되지 않도록 한 칸 띄고 입력을 받아주면 좋습니다. (9/20)
14720번 : 우유 축제
#include <cstdio>
using namespace std;
int main() {
int N, Type, cnt = 0, cur = -1;
scanf("%d", &N);
for(int i=0; i<N; i++) {
scanf("%d", &Type);
if((cnt == 0 && Type == 0)||(cur == 0 && Type == 1)||(cur == 1 && Type == 2)
||(cur == 2 && Type == 0)) cur = Type, cnt++;
}
printf("%d", cnt);
}
처음에는 반드시 딸기우유를 마신다는 조건이 있기 때문에 첫 수열은 반드시 0에서 시작해야 합니다.
따라서 if문의 맨 앞 조건인 cnt가 0이고 Type이 0이 들어오는 경우가 하나 추가되어 있습니다.
그 외에는 빨리 나오는 수부터 먼저 선택하여 진행할 수 있도록 합니다. (그리디 알고리즘) (10/20)
17614번 : 369
#include <cstdio>
using namespace std;
int main() {
int N, cnt = 0;
scanf("%d", &N);
for(int i=1; i<=N; i++) {
int temp = i;
while(temp) {
if(temp%10 == 3 || temp%10 == 6 || temp%10 == 9) cnt++;
temp /= 10;
}
}
printf("%d", cnt);
}
1부터 N까지 중에 등장하는 3, 6, 9 개수의 총합을 구하는 문제입니다.
각 i에 대해 temp로 값을 옮겨주고 temp를 일의 자리부터 하나씩 분해하면서 3, 6, 9가 몇 개 있는지 일일이 세주면 됩니다.
bronze 문제이기 때문에 반복문으로 일일이 검사해도 시간 안에 여유있게 통과 가능합니다. (11/20)
14920번 : 3n+1 수열
#include <cstdio>
using namespace std;
int main() {
int N, cnt = 1;
scanf("%d", &N);
while(1) {
if(N == 1) break;
if(N%2 == 0) N /= 2;
else N = 3*N+1;
cnt++;
}
printf("%d", cnt);
}
문제에 주어진 점화식대로 값을 대입하여 반복문으로 구해주면 됩니다.
첫 입력으로 N=1이 들어올 수도 있기 때문에, 먼저 N이 1인지부터 검사를 해주어야 합니다.
그 외에는 cnt를 이용해 카운트를 해주면 됩니다. (12/20)
4766번 : 일반 화학 실험
#include <cstdio>
using namespace std;
int main() {
double a, b;
scanf("%lf", &a);
while(1) {
scanf("%lf", &b);
if(b == 999) break;
printf("%.2lf\n", b-a);
a = b;
}
}
소숫점 계산을 해야하므로 자료형을 double로 선언해주고, 연산을 수행해주면 됩니다.
측정은 반드시 2번 이상 진행된다고 하였으므로 먼저 a를 입력받고, while문을 열어서 그 때부터 b를 입력받고 b를 a로 넘겨주는 과정을 반복해주면 됩니다.
만약 b가 999라면 while문을 종료해주면 됩니다. (13/20)
15667번 : 2018 연세대학교 프로그래밍 경진대회
#include <cstdio>
using namespace std;
int main() {
int N, i;
scanf("%d", &N);
for(i=1; i<=10000; i++) {
if(1+i+i*i == N) break;
}
printf("%d", i);
}
주어진 공식을 보고 역으로 계산하여 원래의 수를 찾아내는 문제입니다.
식을 세워보면 1 + i + i*i = N이므로 i를 반복문으로 찾아낼 수 있습니다. (14/20)
9094번 : 수학적 호기심
#include <cstdio>
using namespace std;
int main() {
int T, n, m;
scanf("%d", &T);
for(int i=0; i<T; i++) {
int cnt = 0;
scanf("%d %d", &n, &m);
for(int j=1; j<n; j++)
for(int k=j+1; k<n; k++)
if((j*j+k*k+m)%(j*k) == 0) cnt++;
printf("%d\n", cnt);
}
}
주어진 식을 범위 내에서 반복문을 이용해 모두 대입해보면서 가능한 해의 수를 찾으면 되는 문제입니다.
다만 a < b라는 조건이 있으므로, inner loop의 초기값 k = j+1로 설정해주어야 합니다.
그리고 오른쪽 극값도 n 미만으로 잡아주어야 오답을 피할 수 있습니다. (15/20)
3029번 : 경고
#include <cstdio>
using namespace std;
int main() {
int a1, b1, c1, a2, b2, c2, sum1 = 0, sum2 = 0, ans;
scanf("%02d:%02d:%02d\n%02d:%02d:%02d", &a1, &b1, &c1, &a2, &b2, &c2);
sum1 = a1*60*60 + b1*60 + c1;
sum2 = a2*60*60 + b2*60 + c2;
if(sum1 == sum2) {
printf("24:00:00");
return 0;
}
else if(sum2 > sum1) ans = sum2 - sum1;
else ans = sum2 + 24*60*60 - sum1;
printf("%02d:%02d:%02d", ans/3600, (ans%3600)/60, ans%60);
}
두 시간의 차이를 구하는 문제입니다.
일단 두 시간을 모두 초 단위로 변환시켜서 빼주는 방식을 사용했고, 만약 24시를 넘어간다면 sum2에 24시간을 더해서 다시 빼도록 해주었습니다.
그리고 문제 조건에 최소 1초 이상 24시간 이하를 기다린다고 하였으므로 sum1 = sum2인 경우에는 24시간을 기다린 것으로 간주해야 합니다. (16/20)
5613번 : 계산기 프로그램
#include <cstdio>
using namespace std;
int main() {
int b, ans;
char op;
scanf(" %d", &ans);
while(1) {
scanf(" %c", &op);
if(op == '=') break;
scanf(" %d", &b);
if(op == '+') ans += b;
else if(op == '-') ans -= b;
else if(op == '*') ans *= b;
else if(op == '/') ans /= b;
}
printf("%d", ans);
}
이 문제는 간단한 사칙연산을 구현하는 문제인데, 연산이 어디까지 이어지는지 알 수 없으므로 우선 정수 하나를 입력 받고, 그 뒤에 무한 루프를 이용하여 operator가 =인지 검사하여 =일 경우에만 break 하도록 해줍니다.
그 외의 경우에는 연산자를 구분시켜 그 다음에 오는 값을 연산시켜줍니다. (17/20)
15781번 : 헬멧과 조끼
#include <cstdio>
using namespace std;
int main() {
int N, M, max1 = 0, max2 = 0, value;
scanf("%d %d", &N, &M);
for(int i=0; i<N; i++) {
scanf("%d", &value);
if(value > max1) max1 = value;
}
for(int i=0; i<M; i++) {
scanf("%d", &value);
if(value > max2) max2 = value;
}
printf("%d", max1+max2);
}
두 파트의 방어력을 합쳐서 최댓값을 출력하는 문제입니다.
두 개의 최댓값을 따로 구해서 합쳐주면 되며, 각 입력이 10억 이하이므로 둘을 합쳐도 정수형을 벗어나지 않습니다. (18/20)
5612번 : 터널의 입구와 출구
#include <cstdio>
using namespace std;
int main() {
int N, M, sum, a, b, check = 0, Max;
scanf("%d %d", &N, &M);
sum = M;
Max = M;
for(int i=0; i<N; i++) {
scanf("%d %d", &a, &b);
sum = sum+a-b;
if(sum > Max) Max = sum;
if(sum < 0) check = 1;
}
if(!check) printf("%d", Max);
else printf("0");
}
터널의 매 분마다 들어오는 차량과 나가는 차량의 수를 이용하여 sum 값을 갱신해줍니다.
sum 값이 max보다 크다면, max 값을 sum으로 갱신해줍니다.
그리고 max 값은 초기값일 수도 있으므로 초기 m을 max에 저장해주도록 해야 합니다. (19/20)
15780번 : 멀티탭 충분하니?
#include <cstdio>
using namespace std;
int main() {
int N, K, sum = 0, value;
scanf("%d %d", &N, &K);
for(int i=0; i<K; i++) {
scanf("%d", &value);
if(value%2) sum += value/2+1;
else sum += value/2;
}
if(sum >= N) printf("YES");
else printf("NO");
}
멀티탭의 구의 수가 홀수 개일 때는 절반으로 나눈 값 + 1만큼 최대로 꽂을 수 있고, 멀티탭의 구의 수가 짝수일 때는 절반으로 나눈 값만큼 꽂을 수 있으므로 이들을 모두 더해 sum에 저장해주고, sum이 N보다 크거나 같으면 Yes를, 아닐 때는 No를 출력해주도록 하면 됩니다. (20/20)
결과
현재까지 총 525문제를 해결하여 1900등 안쪽까지 도달하였습니다.
'알고리즘 > 백준(BOJ) 문제풀이' 카테고리의 다른 글
[C++ 백준 풀이] 3584번 : 가장 가까운 공통 조상 (Easy LCA) (0) | 2021.12.16 |
---|---|
[C++ 백준 풀이][Bronze III] 기초 연산 20문제 간단 풀이 (3) (0) | 2021.12.16 |
[C++ 백준 풀이][Bronze III] 기초 연산 20문제 간단 풀이 (1) (0) | 2021.12.15 |
[C++ 백준 풀이][Bronze IV] 외국어 문제들 번역 풀이 (0) | 2021.12.15 |
[C++ 백준 풀이][Bronze IV] 20499, 19698, 18408, 19602, 21598, 18411, 18414, 20673, 20976, 18330번 풀이 (0) | 2021.12.15 |