본문 바로가기

알고리즘/IUPC 2022

[백준] 25215번 타이핑 [C++]

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

 

25215번: 타이핑

민겸이는 영어 소문자와 대문자로 이루어진 문자열을 타이핑하기로 했다. 민겸이가 사용할 수 있는 버튼은 26개의 영어 알파벳 버튼과 마름모(◆) 버튼, 별(★) 버튼이다. 각 버튼은 아래와 같이

www.acmicpc.net


문제 설명


먼저 각 각 경우를 생각해야 한다.

 

aaAaa 와 같이 소문자들 사이에 대문자가 1개 있을 경우, 

  • aaa★aa->6번만에 해결 가능
  • aa◆a◆aa->7번만에 해결 가능

aaAAa와 같이 소문자들 사이에 대문자가 2개 있을 경우,

  • aaa★a★a->7번만에 해결 가능
  • aa◆aa◆a->7번만에 해결 가능

aAAAa와 같이 소문자들 사이에 대문자가 3개 있을 경우,

  • aa★a★a★a->8번만에 해결 가능
  • a◆aaa◆a->7번만에 해결 가능

즉 , 중간에 다른 한 문자만 있다면 별을 사용하는 것이 이득, 다른 문자가 2개 있다면 별이든, 마름모든 똑같고, 다른 문자가 3개 이상일 경우에는 마름모를 사용하는 것이 이득이다.

따라서 2개이상일 경우에는 마름모를 사용하도록 정해놓자.

 

이에 따라서 문자열의 앞 부분부터 탐색을 진행하면 원하는 답을 구할 수 있다.

 


코드

#include<iostream>
#include<algorithm>
using namespace std;
string s;
int n;
int result;
bool isSmall(char a) {
	if (a >= 'a')return true;
	else return false;
} //해당 문자가 소문자인지 대문자인지 구분하게 위해 만든 함수
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cin >> s;
	bool curSmall = true; //초기에는 소문자다.
	bool preDiffer = false;
	result = 1;
	if (!isSmall(s[0])) {//만약 맨 첫 글자가 대문자면, 타이핑 2번으로 시작하게 된다.
		result = 2;
		preDiffer = true; //초기의 소문자와 다르기 때문
	}
	for (int i = 1; i < s.length(); i++) {
		result++;
		if (curSmall) {         //각 경우를 나눠준다.
			if (isSmall(s[i])) { //현재 상태가 소문자고, 이번 문자도 소문자일 경우
				preDiffer = false;
			}
			else {    //현재 상태가 소문자고, 이번 문자는 대문자일 경우
				if (preDiffer) {//이전 문자도 대문자 였다면, 마름모를 눌렀다고 가정하고 상태를 바꿔버림		
					curSmall = false;
					preDiffer = false;
				}
				else { //이전문자가 소문자였다면 아직 마름모인지,별인지 모르지만 타이핑을 2번 해야 하긴 함
					result++;
					preDiffer = true;
				}
			}
		}
		else { //위의 소문자와 대문자만 반대로 진행
			if (!isSmall(s[i])) {
				preDiffer = false;
			}
			else {
				if (preDiffer) {
					curSmall = true;
					preDiffer = false;
				}
				else {
					result++;
					preDiffer = true;
				}
			}
		}
	}
	cout << result;
}

경우를 많이 나눠야 해서 헷갈렸던 문제였다.