이번 알고리즘 문제 풀이는 C로 진행했습니다
코드에 오탈자나 문제가 있으면 언제든지 댓글로 알려주세요!
A. 심화 1
1. 새싹
a. 문제지 : 25083
b. 정답
📚 풀이
#include <stdio.h>
int main(){
printf(" ,r'\"7\n");
printf("r`-_ ,' ,/\n");
printf(" \\. \". L_r'\n");
printf(" `~\\/\n");
printf(" |\n");
printf(" |\n");
return 0;
}
2. 킹, 퀸, 룩, 비숍, 나이트, 폰
a. 문제지 : 10871
b. 정답
📚 풀이
#include <stdio.h>
int main(){
int num;
char chess[6] = {1,1,2,2,2,8};
for(int i=0; i<6; i++){
scanf("%d", &num);
printf("%d ", chess[i] - num);
}
return 0;
}
3. 별 찍기 - 7
a. 문제지 : 2444
b. 알고리즘 / 풀이
별찍기 문제를 많이 했지만, 매번 다른 패턴에 실수가 있어서 ㅠㅠ 이번에는 내 방식대로 풀이를 해봤다
위와같이 위 아래 대칭일 경우 풀이 방법에서 위, 아래 출력형식을 다르게 하는 방법을 많이 사용하지만
왠지 모르게 머리에 안들어와서 그냥 한번에 출력하는 방식을 사용해서 풀이해봤다
- 사용자로부터 N값을 입력받음
- 행 출력 : for 반복문을 이용, 반복 범위는 1부터 2*n-1까지
- 열 출력 : 현재 행의 별의 개수를 나타내는 star, 별의 증감을 나타내는 sumb 초기화
a) if 조건문으로 중간행 확인 후 sumb의 값을 변경해줌
b) 입력받은 숫자보다 1 작은 값 만큼 공백 출력
c) 출력 후 조건에 따른 별 찍기
d) 출력 후 별 조건 변경 후 줄바꿈 - 모든 행 출력이 끝나면 종료
c. 정답
📚 풀이 1 : 별의 개수를 변수화 해 출력하는 방법
#include <stdio.h>
#include <stdlib.h> // abs 함수를 사용하기 위해 포함
int main(){
int N, star = 1, sumb = 2;
scanf("%d", &N); // 사용자로부터 N 값을 입력 받음
// 행 출력
for(int i = 1; i <= 2 * N - 1; i++){ // 1부터 2 * N - 1까지 반복하는 반복문
// 열 출력
// 알고리즘
// 1) 입력받은 숫자보다 1 작은 값만큼 공백 출력
// 2) 출력 후 그 전 출력한 값 기억(없다면 1)해 2 추가해 별 찍기
// 3) i > N 이라면 위 알고리즘 반대로 행동
if(i == N){ // i가 N과 같다면 아래에서 별의 개수가 줄어드는 부분이므로 방향을 바꿈
sumb = -2; // sumb 값을 -2로 변경하여 별의 개수를 줄이는 방향으로 전환
} else {
for(int j = 0; j < abs(N - i); j++){ // 입력받은 숫자보다 1 작은 값만큼 공백 출력
printf(" ");
}
}
if(star == 1){ // 처음에 별을 한 개만 출력할 때
printf("*");
} else {
for(int k = 0; k < star; k++){ // 별 출력
printf("*");
}
}
star += sumb; // 다음 행의 별 개수를 계산하기 위해 star 변수 갱신
printf("\n"); // 한 행 출력이 끝났으므로 줄바꿈
}
return 0;
}
📚 풀이 2 : 위 아래 구분지어 출력하는 방법
#include <stdio.h>
#include <stdlib.h>
int main() {
int N;
scanf("%d", &N); // 사용자로부터 N 값을 입력 받음
// 위쪽 영역 출력
for (int i = 1; i <= N; i++) { // 위쪽 영역은 1부터 N까지 반복하는 반복문
// 공백 출력 부분
for (int j = 1; j <= N - i; j++) { // 입력값 N보다 작은 값만큼 공백을 출력하여 오른쪽 정렬하도록 줄맞춤
printf(" ");
}
// 별 출력 부분
for (int j = 1; j <= 2 * i - 1; j++) { // 현재 행에서 출력해야 할 별의 개수는 (2 * i - 1)
printf("*");
}
printf("\n"); // 한 행 출력이 끝났으므로 줄바꿈
}
// 아래쪽 영역 출력
for (int i = N - 1; i >= 1; i--) { // 아래쪽 영역은 N - 1부터 1까지 반복하는 반복문
// 공백 출력 부분
for (int j = 1; j <= N - i; j++) { // 입력값 N보다 작은 값만큼 공백을 출력하여 오른쪽 정렬하도록 줄맞춤
printf(" ");
}
// 별 출력 부분
for (int j = 1; j <= 2 * i - 1; j++) { // 현재 행에서 출력해야 할 별의 개수는 (2 * i - 1)
printf("*");
}
printf("\n"); // 한 행 출력이 끝났으므로 줄바꿈
}
return 0;
}
4. 팰린드롬인지 확인하기
a. 문제지 : 2562
b. 정답
📚 풀이 1
#include <stdio.h>
#include <string.h>
int main() {
char word[101]; // 최대 100개의 문자로 이루어진 문자열을 담을 배열
scanf("%s", word); // 사용자로부터 문자열 입력 받음
int len = strlen(word); // 입력된 문자열의 길이를 계산
for (int i = 0; i <= len / 2; i++) { // 문자열의 반 이하만큼 반복
if (word[i] == word[len - 1 - i]) { // 대칭 위치에 있는 문자를 비교하여 같으면
if (i == len / 2) { // 회문을 확인하는 반복문이 끝까지 실행되면 회문임을 의미
printf("1\n"); // 회문일 경우 1 출력
} else {
// 아무 동작도 하지 않음
// 대칭 위치에 있는 문자가 같더라도 다음 반복에서 검사해야 할 문자가 있을 수 있으므로 이 부분은 비워둠
}
} else { // 대칭 위치에 있는 문자가 다를 경우
printf("0\n"); // 회문이 아니므로 0 출력
break; // 반복문 종료
}
}
return 0;
}
👉 위 코드를 반대로 생각해보면 문자가 다를 경우에만 반복문을 깨고 탈출하면 됨!
📚 풀이 2 : 풀이 1 코드 정리
#include <stdio.h>
#include <string.h>
int main() {
char word[101]; // 최대 100개의 문자로 이루어진 문자열을 담을 배열
scanf("%s", word); // 사용자로부터 문자열 입력 받음
int len = strlen(word); // 입력된 문자열의 길이를 계산
int isPalindrome = 1; // 팰린드롬 여부를 나타내는 변수, 초기값은 1로 설정
for (int i = 0; i < len / 2; i++) {
if (word[i] != word[len - 1 - i]) { // 대칭 위치에 있는 문자를 비교하여 다를 경우
isPalindrome = 0; // 팰린드롬이 아님을 표시
break; // 반복문 종료
}
}
printf("%d\n", isPalindrome); // 팰린드롬 여부 출력
return 0;
}
5. 단어 공부
a. 문제지 : 1157
b. 알고리즘 / 풀이
- 알파벳 등장 횟수 세기
a) 주어진 문자열을 순회하면서 각 문자의 등장 횟수를 카운트하는 배열을 생성
b) 배열의 크기는 26 (알파벳 개수)로 설정
c) 문자열을 순회하면서 각 문자를 대문자로 변환
d) 해당 문자가 알파벳인 경우 카운트 배열의 인덱스를 계산하여 카운트를 증가 - 가장 많이 나타난 알파벳 찾기:
a) 등장 횟수를 카운트한 배열을 순회하면서 가장 많이 나타난 알파벳을 찾기
b) 만약 가장 많이 나타난 알파벳이 여러 개라면 ?로 처리
c. 정답
📚 풀이
#include <stdio.h>
#include <ctype.h> // toupper 함수를 사용하기 위해 포함
int main() {
char word[1000001]; // 최대 1,000,000 길이의 문자열을 담을 배열
int count[26] = {0}; // 알파벳 개수를 저장할 배열, 초기값은 0
scanf("%s", word); // 문자열 입력 받음
for (int i = 0; word[i] != '\0'; i++) { //문자열 끝까지 순회
char c = toupper(word[i]); // 대문자로 변환
count[c - 'A']++; // 해당 알파벳 카운트 증가
}
int maxCount = 0; // 가장 많은 알파벳의 개수
char mostFrequent = '?'; // 가장 많이 나타난 알파벳, 초기값은 '?'
for (int i = 0; i < 26; i++) {
if (count[i] > maxCount) { // 더 많은 알파벳이 나타났을 경우
maxCount = count[i];
mostFrequent = 'A' + i; // 해당 알파벳 설정
} else if (count[i] == maxCount) { // 같은 개수의 알파벳이 나타난 경우
mostFrequent = '?';
}
}
printf("%c\n", mostFrequent); // 결과 출력
return 0;
}
6. 크로아티아 알파벳
a. 문제지 : 2941
b. 알고리즘 / 풀이
방식 1) 크로아티아 알파벳을 표현하는 문자들의 규칙성을 가지고 문제 풀이
- 최대 100글자의 단어를 입력 받음
- 입력된 단어의 길이를 계산하여 length 변수에 저장
- 크로아티아 알파벳 개수를 세기 위한 count 변수를 초기화
- 문자열을 한 글자씩 순회하며 크로아티아 알파벳을 판별
- 각 알파벳의 경우에 따라 조건문을 사용하여 크로아티아 알파벳을 확인하고 처리
- 해당 크로아티아 알파벳의 길이만큼 인덱스를 증가시켜 한 문자로 처리
- 조건에 해당하지 않으면 한 글자로 처리하고 count를 증가
- 순회가 끝나면 count에 저장된 크로아티아 알파벳 개수를 출력
방식 2) 크로아티아 알파벳을 문자열로 등록 후 카운트
- 최대 100글자의 단어를 입력받음
- 크로아티아 알파벳을 표현하는 문자열 배열 target을 정의
- target 배열의 길이를 계산하여 length 변수에 저장
- 입력된 문자열의 길이를 계산하여 strLen 변수에 저장
- 크로아티아 알파벳의 개수를 저장할 count 변수를 초기화
- 문자열을 한 글자씩 순회하며 크로아티아 알파벳을 찾기
- 내부 루프를 사용하여 target 배열의 각 크로아티아 알파벳과 현재 위치의 문자열을 비교
- strncmp 함수를 사용하여 현재 위치부터 target[j]의 길이만큼 비교
- 만약 현재 위치부터 target[j]와 길이가 같은 문자열이라면 크로아티아 알파벳을 발견한 것으로 판단
- count 변수를 증가시키고, 해당 크로아티아 알파벳의 길이만큼 인덱스를 증가
- 만약 크로아티아 알파벳을 찾지 못했다면 한 글자로 처리하고 count를 증가
- 순회가 끝나면 최종적으로 count에 저장된 크로아티아 알파벳의 개수를 출력
c. 정답
📚 풀이 1
#include <stdio.h>
#include <string.h>
int main() {
char word[101];
scanf("%s", word); // 최대 100글자의 단어를 입력 받음
int length = strlen(word); // 입력된 단어의 길이 계산
int count = 0; // 크로아티아 알파벳 개수를 세는 변수
for (int i = 0; i < length; i++) {
if (word[i] == 'c' && (i + 1) < length) {
if (word[i + 1] == '=' || word[i + 1] == '-') {
i++; // 'c=' 또는 'c-'를 만나면 한 문자로 처리하고 인덱스 증가
}
} else if (word[i] == 'd' && (i + 1) < length) {
if (word[i + 1] == 'z' && (i + 2) < length && word[i + 2] == '=') {
i += 2; // 'dz='를 만나면 한 문자로 처리하고 인덱스 증가
} else if (word[i + 1] == '-') {
i++; // 'd-'를 만나면 한 문자로 처리하고 인덱스 증가
}
} else if ((word[i] == 'l' || word[i] == 'n') && (i + 1) < length) {
if (word[i + 1] == 'j') {
i++; // 'lj' 또는 'nj'를 만나면 한 문자로 처리하고 인덱스 증가
}
} else if ((word[i] == 's' || word[i] == 'z') && (i + 1) < length) {
if (word[i + 1] == '=') {
i++; // 's=' 또는 'z='를 만나면 한 문자로 처리하고 인덱스 증가
}
}
count++; // 각 경우에 해당하지 않으면 한 글자로 처리하고 count 증가
}
printf("%d\n", count); // 크로아티아 알파벳 개수 출력
return 0;
}
📚 풀이 2
#include <stdio.h>
#include <string.h>
int main() {
char str[101];
scanf("%s", str); // 최대 100글자의 단어 입력 받음
const char* target[8] = {"c=", "c-", "dz=", "d-", "lj", "nj", "s=", "z="};
int length = sizeof(target) / sizeof(target[0]); // target 배열의 길이 계산
int strLen = strlen(str); // 입력된 문자열의 길이 계산
int count = 0; // 크로아티아 알파벳 개수 카운트 변수
for (int i = 0; i < strLen; i++) { // 문자열을 순회하며 크로아티아 알파벳을 찾음
int found = 0; // 크로아티아 알파벳이 발견되었는지 여부를 나타내는 변수
for (int j = 0; j < length; j++) {
// 문자열의 현재 위치부터 target[j] 길이만큼을 비교하여 크로아티아 알파벳 검사
if (strncmp(str + i, target[j], strlen(target[j])) == 0) {
count++; // 크로아티아 알파벳 개수 증가
found = 1; // 크로아티아 알파벳 발견 표시
i += strlen(target[j]) - 1; // 치환된 문자열 길이만큼 인덱스 증가
break; // 문자열이 치환되었으면 다음 문자로 이동
}
}
if (!found) {
count++; // 크로아티아 알파벳이 아니면 한 글자로 처리
}
}
printf("%d\n", count); // 크로아티아 알파벳 개수 출력
return 0;
}
7. 그룹 단어 체커
a. 문제지 : 1316
b. 알고리즘 / 풀이
일단 문제부터 쉽게 이해해보자면
그룹단어란 단어에 같은 알파벳의 중복된 연속적인 형태는 가능하지만, 연속되지 않은 형태는 불가능하다는 소리!
- 단어의 개수 N을 입력
- 그룹 단어가 아닌 개수를 나타내는 count 변수를 초기화
- N번 반복하면서 각 단어에 대해 다음 과정을 수행
a) 단어를 입력
b) 알파벳의 등장 여부를 저장하는 배열 alphabet을 초기화
c) 단어의 길이를 계산
d) 알파벳 검사 시 첫 번째 단어를 제외하고 두번 째 부터 만약 전 알파벳이 이번 알파벳과 다르고, 배열이 카운트 되어있다면 카운트 하고 조건문 빠져나감
e) 나머지 경우는 알파벳 배열 카운트 - 모든 단어에 대한 검사가 끝나면 그룹 단어의 개수(N-count)를 출력
c. 정답
📚 풀이
#include <stdio.h>
#include <string.h>
int main() {
int N;
scanf("%d", &N); // 단어의 개수 입력 받음
int count = 0; // 그룹 단어 개수 카운트 변수
for (int i = 0; i < N; i++) {
char word[101];
int alphabet[26] = {0}; // 알파벳의 등장 여부를 저장하는 배열
scanf("%s", word); // 단어 입력 받음
int len = strlen(word); // 단어의 길이 계산
for (int j = 0; j < len; j++) {
if (j == 0 || word[j - 1] != word[j]) { // 첫 글자이거나 이전 글자와 다른 경우
if (alphabet[word[j] - 'a'] != 0) { // 이미 등장한 알파벳이라면
count++; // 그룹 단어가 아님
break; // 더 이상 검사할 필요 없음
}
alphabet[word[j] - 'a']++; // 알파벳 등장 여부 표시
}
}
}
printf("%d\n", N - count); // 그룹 단어의 개수 출력
return 0;
}
8. 너의 평점은
a. 문제지 : 20206
b. 풀이 / 알고리즘
항상 for문만 쓰는 것 같아서 while문을 사용하려고 했는데
여기서 continue를 사용한걸 까먹고 i++이 왜 안되나,, 한참 고민했다ㅠㅠ
continue문의 개념을 확실히 집고 갈 수 있었다!
chatgpt는 항상 올바른 답을 제공하는건 아니지만 너무 큰 도움을 준다 ^0^
c. 정답
📚 풀이 : for 반복문을 활용
#include <stdio.h>
#include <string.h>
int main() {
double total_score = 0.0; // 전공평점의 합을 저장하는 변수
double total_credit = 0.0; // 총 학점을 저장하는 변수
for (int i = 0; i < 20; i++) {
char subject[51], grade[3]; // 과목명과 등급을 저장할 배열
double credit; // 학점을 저장하는 변수
double grade_score = 0.0; // 등급에 따른 과목평점을 저장하는 변수
scanf("%s %lf %s", subject, &credit, grade); // 과목 정보 입력 받음
// 등급에 따른 과목평점 계산
if (strcmp(grade, "A+") == 0) {
grade_score = 4.5;
} else if (strcmp(grade, "A0") == 0) {
grade_score = 4.0;
} else if (strcmp(grade, "B+") == 0) {
grade_score = 3.5;
} else if (strcmp(grade, "B0") == 0) {
grade_score = 3.0;
} else if (strcmp(grade, "C+") == 0) {
grade_score = 2.5;
} else if (strcmp(grade, "C0") == 0) {
grade_score = 2.0;
} else if (strcmp(grade, "D+") == 0) {
grade_score = 1.5;
} else if (strcmp(grade, "D0") == 0) {
grade_score = 1.0;
} else if (strcmp(grade, "F") == 0) {
grade_score = 0.0;
} else if (strcmp(grade, "P") == 0) {
continue; // P 등급은 계산에서 제외
}
total_score += credit * grade_score; // 해당 과목의 학점과 등급을 곱하여 전공평점의 합에 더함
total_credit += credit; // 해당 과목의 학점을 총 학점에 더함
}
if (total_credit == 0.0) {
printf("0.00000\n"); // 학점이 0이면 전공평점도 0.00000으로 출력
} else {
double avg_score = total_score / total_credit; // 전공평점의 평균 계산
printf("%.5lf\n", avg_score); // 전공평점의 평균을 소수 다섯째 자리까지 출력
}
return 0;
}
📚 풀이 : while 반복문을 활용
#include <stdio.h>
#include <string.h>
int main() {
double total_score = 0.0; // 전공평점의 합을 저장하는 변수
double total_credit = 0.0; // 총 학점을 저장하는 변수
int i = 0; // 반복 횟수를 저장하는 변수
while (i < 20) {
char subject[51], grade[3]; // 과목명과 등급을 저장할 배열
double credit; // 학점을 저장하는 변수
double grade_score = 0.0; // 등급에 따른 과목평점을 저장하는 변수
scanf("%s %lf %s", subject, &credit, grade); // 과목 정보 입력 받음
// 등급에 따른 과목평점 계산
if (strcmp(grade, "A+") == 0) {
grade_score = 4.5;
} else if (strcmp(grade, "A0") == 0) {
grade_score = 4.0;
} else if (strcmp(grade, "B+") == 0) {
grade_score = 3.5;
} else if (strcmp(grade, "B0") == 0) {
grade_score = 3.0;
} else if (strcmp(grade, "C+") == 0) {
grade_score = 2.5;
} else if (strcmp(grade, "C0") == 0) {
grade_score = 2.0;
} else if (strcmp(grade, "D+") == 0) {
grade_score = 1.5;
} else if (strcmp(grade, "D0") == 0) {
grade_score = 1.0;
} else if (strcmp(grade, "F") == 0) {
grade_score = 0.0;
} else if (strcmp(grade, "P") == 0) {
i++; // P 등급의 경우에도 반복 횟수 증가
continue; // P 등급은 계산에서 제외
}
total_score += credit * grade_score; // 해당 과목의 학점과 등급을 곱하여 전공평점의 합에 더함
total_credit += credit; // 해당 과목의 학점을 총 학점에 더함
i++; // 반복 횟수 증가
}
if (total_credit == 0.0) {
printf("0.00000\n"); // 학점이 0이면 전공평점도 0.00000으로 출력
} else {
double avg_score = total_score / total_credit; // 전공평점의 평균 계산
printf("%.5lf\n", avg_score); // 전공평점의 평균을 소수 다섯째 자리까지 출력
}
return 0;
}
'자료구조와 알고리즘 > 문제풀이' 카테고리의 다른 글
[Baekjoon] 단계별로 풀어보기 : 일반 수학 1 (0) | 2023.08.25 |
---|---|
[Baekjoon] 단계별로 풀어보기 : 2차원 배열 (0) | 2023.08.25 |
[Baekjoon] 단계별로 풀어보기 : 문자열 (0) | 2023.08.17 |
[Baekjoon] 단계별로 풀어보기 : 1차원 배열 (0) | 2023.08.16 |
[Baekjoon] 단계별로 풀어보기 : 반복문 (0) | 2023.08.16 |