천천히 빛나는

백준 단계 6 : 심화 1 (C++) 본문

C++/BAEKJOON (C++)

백준 단계 6 : 심화 1 (C++)

까만콩 •ᴥ• 2023. 9. 3. 01:31

25083. 아래 예제와 같이 새싹을 출력하시오.

#include<iostream>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << "         ,r'\"7\n"
        << "r`-_   ,'  ,/\n"
        << " \\. \". L_r'\n"
        << "   `~\\/\n"
        << "      |\n"
        << "      |";
    return 0;
}

\' : single quote character in the text

\" : double quote charater in the text

\\ : backslash cahracter in the the text

 

 

 

3003. 동혁이는 오래된 창고를 뒤지다가 낡은 체스판과 피스를 발견했다. 체스판의 먼지를 털어내고 걸레로 닦으니 그럭저럭 쓸만한 체스판이 되었다. 하지만, 검정색 피스는 모두 있었으나, 흰색 피스는 개수가 올바르지 않았다.

#include <iostream>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int piece[] = { 1, 1, 2, 2, 2, 8 };
    int num;
    for (int i = 0; i < 6; i++) {
        cin >> num;
        piece[i] -= num;
    }
    for (int i = 0; i < 6; i++) {
        cout << piece[i] << " ";
    }
    return 0;
}

간단하게 배열로 선언하고 풀 수 있는 문제이다

 

 

 

2444. 예제를 보고 규칙을 유추한 뒤에 별을 찍어 보세요.

#include <iostream>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j < n - i; j++)
        {
            cout << " ";
        }
        for (int j = 0; j < 2 * i-1; j++)
        {
            cout << "*";
        }
        cout << "\n";
    }

    for (int i = n-1; i >= 1; i--)
    {
        for (int j = 0; j < n - i; j++)
        {
            cout << " ";
        }
        for (int j = 0; j < 2 * i - 1; j++)
        {
            cout << "*";
        }
        cout << "\n";
    }
    
    return 0;
}

이중 for문을 이용하여 구현하였다.

 

 

 

10988. 알파벳 소문자로만 이루어진 단어가 주어진다. 이때, 이 단어가 팰린드롬인지 아닌지 확인하는 프로그램을 작성하시오. 팰린드롬이란 앞으로 읽을 때와 거꾸로 읽을 때 똑같은 단어를 말한다. 

#include <iostream>
#include <algorithm>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    string original;
    cin >> original;
    string palindrome = original;
    for (int i = 0; i < original.length()/2; i++)
    {
        swap(palindrome[i], palindrome[(original.length()-1-i)]);
    }
    cout << (original == palindrome);
    return 0;
}

나는 모두  swap을 해서 최종 결과를 비교하는 방식으로 구현하였다.

 

#include <iostream>
#include <algorithm>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    string original;
    cin >> original;
    for (int i = 0; i < original.length()/2; i++)
    {
        if (original[i] != original[original.length() -1 -i])
        {
            cout << 0;
            return 0;
        }
    }
    cout << 1;
    return 0;
}

하지만 굳이 모두 swap 하지 않고 하나하나 비교하는 방법도 존재한다. 코드 길이는 첫번째 코드가 더 짧았다.

 

reverse(temp.begin(), temp.end());

reverse 함수는 first를 포함한 인덱스 부터 last 바로 전 인덱스까지의 요소들을 거꾸로 뒤집는 함수이다. reverse 함수를 사용하면 for문 없이 더 간단하게 코드를 작성할 수 있을 것이다.

int a[] = { 4, 5, 6, 7 };
reverse(a, a+2);

// {5, 4, 6, 7} 로 됨

위 코드는 reverse 함수 예제이다. 

 

 

 

1157. 알파벳 대소문자로 된 단어가 주어지면, 이 단어에서 가장 많이 사용된 알파벳이 무엇인지 알아내는 프로그램을 작성하시오. 단, 대문자와 소문자를 구분하지 않는다.

#include <iostream>
#include <algorithm>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    string word;
    cin >> word;
    int alpa[26] = { 0 };
    for (int i = 0; i < word.length(); i++)
    {
        word[i] = toupper(word[i]);
        alpa[word[i] - 'A']++;
    }
    int max = 0;
    int index = -1;
    for (int i = 0; i < 26; i++)
    {
        if (alpa[i] > max)
        {
            max = alpa[i];
            index = i;
        }
    }
    for (int i = 0; i < 26; i++)
    {
        
        if ((alpa[i] == max) && (i != index)) {
            cout << '?';
            return 0;
        }
    }
    cout << (char)(index + 'A');
    return 0;
}

이건 바로 풀지 못하고 다른 분들의 코드를 참조하여 작성하였다.

먼저 a부터 z까지 총 26개가 있고 이를 이용해서 카운트를 한다. 출력이 모두 대문자이므로 toupper 함수를 사용하였다. 소문자로 만들려면 tolower 함수를 사용하면 된다. 

각 문자의 빈도수를 저장하고 가장 높은 빈도수의 index를 찾는다. 그리고 중복되는 빈도수 값을 가졌는지 확인한다.

 

 

 

※2941. 예전에는 운영체제에서 크로아티아 알파벳을 입력할 수가 없었다. 따라서, 다음과 같이 크로아티아 알파벳을 변경해서 입력했다. 예를 들어, ljes=njak은 크로아티아 알파벳 6개(lj, e, š, nj, a, k)로 이루어져 있다. 단어가 주어졌을 때, 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력한다. dž는 무조건 하나의 알파벳으로 쓰이고, d와 ž가 분리된 것으로 보지 않는다. lj와 nj도 마찬가지이다. 위 목록에 없는 알파벳은 한 글자씩 센다.

#include <iostream>
#include <algorithm>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    string str;
    int count = 0;
    cin >> str;
    for (int i = 0; i < str.length(); i++)
    {
        if ((str[i] == 'd') && (i <= str.length() - 1)) {
            if ((i <= str.length() - 2)&&((str[i + 1] == 'z') && (str[i + 2] == '='))) {
                i += 2;
            }
            else if ((str[i + 1] < 'a') || (str[i + 1] > 'z')) {
                i++;
            }
        }
        else if ((str[i] == 'c') || (str[i] == 's') || (str[i] == 'z')) {
            if (((str[i + 1] < 'a') || (str[i + 1] > 'z')) && (i <= str.length() - 1)) {
                i++;
            }
        }
        else if ((i <= str.length()-1)&&(((str[i] == 'l')||(str[i] == 'n')) && (str[i + 1] == 'j'))) {
            i++;
        }
        count++;
    }
    
    cout << count;
    return 0;
}

나는 하나하나 찾아서 count를 늘리는 코드를 작성하였는데, 이렇게 하면 굉장히 비효율적이다. 정답은 맞긴 한다.

 

#include <iostream>
#include <algorithm>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    string str;
    cin >> str;
    string croatian[] = { "c=","c-","dz=","d-","lj","nj","s=","z=" };
    for (int i = 0; i < 8; i++)
    {
        while (1) {
            if (str.find(croatian[i])!=-1) {
                str.replace(str.find(croatian[i]), croatian[i].length(), "#");
            }
            else {
                break;
            }
        }
    }
    cout << str.length();
    return 0;
}

findreplace 함수가 핵심이 되는 코드이다.

 

<algorithm>의 find()함수

#include <algorithm>
find(begin, end, value);

begin ~ end 의 원소 중(end는 포함되지 않음)에 value에 해당하는 주소를 반환한다. 일치하는 원소가 없을 경우에는 end가 반환된다. 

 

<string>의 find()함수

#include <string>
string str;
str.find(value);

문자열 내에서 value 값을 찾고 일치하는 값이 있다면 value의 첫번째 인덱스를 반환한다. 일치하는 값이 없으면 string::npos를 반환한다.  해당 값이 없을때 npos를 반환하게 되는데, npos는 unsigned int이다. int로 변환했을 때 대응되는 값이 -1이 된다. 여러개여도 첫번째 인덱스만을 반환한다.

 

<string>의 replace()함수

#include <string>
string str;
str.replace(시작점, 변환개수, 대체할문자열);

시작점부터 변환개수개만큼의 굴자를 대체할문자열로 변환하게 된다.

 

 

 

1316. 그룹 단어란 단어에 존재하는 모든 문자에 대해서, 각 문자가 연속해서 나타나는 경우만을 말한다. 예를 들면, ccazzzzbb는 c, a, z, b가 모두 연속해서 나타나고, kin도 k, i, n이 연속해서 나타나기 때문에 그룹 단어이지만, aabbbccb는 b가 떨어져서 나타나기 때문에 그룹 단어가 아니다. 단어 N개를 입력으로 받아 그룹 단어의 개수를 출력하는 프로그램을 작성하시오.

#include <iostream>
#include <string>
using namespace std;
int main() {
    int num;
	string str;
	cin >> num;
	int count = 0;
	bool group = 1;
	for (int i = 0; i < num; i++)
	{
		cin >> str;
		for (int j = 0; j < str.length(); j++)
		{
			int last = j;
			for (int k = j+1; k < str.length(); k++)
			{
				if (str[j] == str[k]) {
					if (last != k - 1) {
						group = 0;
						break;
					}
					else {
						last = k;
					}
				}
			}
			if (group == 0)
				break;
		}
		if (group == 1) {
			count++;
		}
		group = 1;
	}
	cout << count;
    return 0;
}

내 코드에서는 for문을 3개 사용했다. 물론 잘 작동하지만 중첩된 for문을 최대한 조금 이용하는 것이 효율적인 코드라고 생각했다.

 

#include <iostream>
#include <string>
using namespace std;
int main() {
    int num;
	string str;
	cin >> num;
	int count = 0; // 그룹단어가 아닐 경우 count
	bool alphabet[26] = { 0, };
	for (int i = 0; i < num; i++)
	{
		cin >> str;
		alphabet[str[0] - 'a'] = 1;

		for (int j = 1; j < str.length(); j++)
		{
			if (str[j] == str[j - 1]) {
				continue;
			}
			else if ((str[j] != str[j - 1]) && (alphabet[str[j] - 'a'] == 1)) {
				count++; // 그룹단어가 아니다
				break;
			}
			else {
				alphabet[str[j] - 'a'] == 1;
			}
		}
	}

	count << num - count;
    return 0;
}

알파벳이 총 26개라는 점을 이용하여 계산하는 식이다. 여기서는 이중 for문이 사용된다.

 

https://hagisilecoding.tistory.com/64

 

백준 1316 그룹 단어 체커 c++ [컴공과고씨]

https://www.acmicpc.net/problem/1316 1316번: 그룹 단어 체커 그룹 단어란 단어에 존재하는 모든 문자에 대해서, 각 문자가 연속해서 나타나는 경우만을 말한다. 예를 들면, ccazzzzbb는 c, a, z, b가 모두 연속

hagisilecoding.tistory.com

이와 같은 방식도 있는데 현재는 이해가 되지 않아서 추후 공부 후 설명을 추가하도록 하겠다.

 

 

25206. 인하대학교 컴퓨터공학과를 졸업하기 위해서는, 전공평점이 3.3 이상이거나 졸업고사를 통과해야 한다. 그런데 아뿔싸, 치훈이는 깜빡하고 졸업고사를 응시하지 않았다는 사실을 깨달았다! 치훈이의 전공평점을 계산해주는 프로그램을 작성해보자.

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
	string str;
	string grade[] = { "A+", "A0", "B+", "B0", "C+", "C0", "D+", "D0", "P", "F" };
	float sum = 0;
	float weight = 0;
	float sum_weight = 0;
	for (int i = 1; i <= 60; i++)
	{
		if ((i+1) % 3 == 0) {
			cin >> weight;
			continue;
		}
		cin >> str;
		if (i % 3 == 0) {
			if (str != "P") {
				{
					float temp = (4.5 - (find(begin(grade), end(grade), str) - begin(grade)) / 2) >= 0.0 ? (4.5 - (find(begin(grade), end(grade), str) - begin(grade)) / 2.0)  :  0.0;
					sum += weight * temp;
					sum_weight += weight;
				}
			}
		}
	}
	cout << sum / sum_weight;
	return 0;
}

cin으로 연속으로 받을 수 있다는 것을 잠시 잊어서 cin이 나누어져 있는데 그러지 않아도 된다는 것을 알았다... 

나는 find 함수를 이용해서 index를 찾고 그걸 점수로 반환했는데, 그렇게 하지 않고 간결하게 짤 수 있었다.

 

1) if문으로 A+일 때, B+일 때 하나하나 작성

2) 배열을 이용하되, 해당되는 학점이 나올 때까지 -0.5하기

https://maloveforme.tistory.com/62

 

[백준] 25206 with C++

문제설명 입출력 예제 개념 학점의 평균을 계산하는 문제다. 학점을 계산하는 방법은 다음과 같다. 전공 학점: 학점 * 과목 평점 전공 학점 평균: 전공 학점 / 총 학점 P 과목은 제외 따라서 전공

maloveforme.tistory.com

3) map 이용해서 풀기

map은 key와 value 쌍으로 이루어진 트리이다. 

map<key, value> map1;
map<string, int> m; // 예시

map은 key를 기준으로 정렬하며 오름차순으로 정렬한다. map을 사용하기 위해서는 #include<map>을 써야한다.

map<std::string, float> grades =
		{ {"A+", 4.5}, {"A0", 4.0}, {"B+", 3.5},
		  {"B0", 3.0}, {"C+", 2.5}, {"C0", 2.0},
		  {"D+", 1.5}, {"D0", 1.0}, {"F", 0} };

이와 같이 초기화할 수도 있다.

map<string, double> grade;
grade["A+"] = 4.5;
grade["A0"] = 4.0;
grade["B+"] = 3.5;
grade["B0"] = 3.0;
grade["C+"] = 2.5;
grade["C0"] = 2.0;
grade["D+"] = 1.5;
grade["D0"] = 1.0;
grade.insert({ "F", 0.0 });

이렇게 직접 추가하거나 insert를 사용할 수도 있다.

#include <iostream>
#include <map>
using namespace std;
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	map<string, double> grades;
	grades["A+"] = 4.5;
	grades["A0"] = 4.0;
	grades["B+"] = 3.5;
	grades["B0"] = 3.0;
	grades["C+"] = 2.5;
	grades["C0"] = 2.0;
	grades["D+"] = 1.5;
	grades["D0"] = 1.0;
	grades.insert({ "F", 0.0 });

	float totalScore = 0, totalGrade = 0;

	for (int i = 0; i < 20; i++)
	{
		string name, grade;
		float score;

		cin >> name >> score >> grade;

		if (grade == "P")
			continue;

		totalScore += score;
		totalGrade += score * grades[grade];
	}

	cout << totalGrade / totalScore << '\n';

	return 0;
}

map을 사용한 최종 코드이다.

 

이번 코드에서 사용한 map 함수 외에도 다양한 함수는 아래 티스토리를 참고하면 된다.

https://life-with-coding.tistory.com/305

 

[C++][STL] map 사용법 정리

인트로 안녕하세요. 오늘은 C++ STL 연관 컨테이너 중 하나인 map에 대해 알려드리겠습니다. 목차 1) Map이란? 2) Map 기본 형태 3) Map 정렬 4) Map 사용방법 - 헤더 포함 - map 선언 - search : map에서 데이터

life-with-coding.tistory.com