본문 바로가기

코드포스

[코드포스] Practice 1 후기

코포.. 코드포스.. 처음으로 여기 문제 풀어봤다. 주변에서 코포 블루니 민트니 그런 얘기를 듣긴 들어서 존재는 알았는데 나랑 관련 없는 곳이라 생각하고 그냥 백준만 풀었었다. 그러다 코포..! 연습문제를 풀었다.

 

문제는 총 5문제고 두시간동안 풀었다. 영어문제.. 영어다.. 그래서 많이 겁먹고 시작했음.

 

 

 

보면 알겠지만 헤맸다. 그냥 바로바로 떠오르는 대로 코드 짜다가 갑자기 쉬운 방법이 떠올라서 방향을 틀었다. 그래서 쉬운 문제였는데 30분을 썼다ㅋㅋ 

 

#include <iostream>
 
using namespace std;
 
int main() {
    int n;
    scanf("%d", &n);
    printf("%d", n/3+(n+2)/3);
}

나는 이렇게 풀었다. 규칙 찾아서 식을 바로 적었음.

 

이렇게 말고도 항상 1->2->1->2가 최선이므로 3으로 나눠준 다음 2를 곱하고 (1->2가 한 세트라 *2 해야함) 뒤에 ->1 이랑 ->2가 있으므로 나눠떨어지지 않는다면 1을 더하면 된다. 

int ans = n / 3 * 2;

if(n%3 != 0)
	ans++;
    
printf("%d", ans);

 


 

이 문제는 이해를 잘못 했다. 양말이 0이 되면 끝나는 줄 알았는데 0이 되더라도 양말을 받아서 다음 날 신을 수 있으면 괜찮은거였음. 그래도 1번처럼 완전 헤매지 않아서 20분 정도 걸렸다.

 

#include <iostream>
 
using namespace std;
 
int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    int day = 1;
    for(int i = 1; ; ){
        if(n <= 0)
           break;
        n--;
        if(day == m*i){
            i++; n++;
        }
        day++;
    }
    printf("%d", --day);
}

나는 -> 양말의 개수 0인지 확인 -> 양말 하나 신음 -> day가 m*i일인지 확인 이렇게 짰는데 내 코드보다 북님 코드가 더 깔쌈한 것 같다. 지금 보니 i는 너무 쓸모없어 보인다. 왜 저렇게 짰지? 푼지 오래돼서 어떤 생각으로 짰는지 기억이 안 난다. 아무튼 아래 코드가 마음에 든다는 소리다. 

 

#include <iostream>
using namespace std;

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    
    int day = 0;
    
    while(n > 0){
        day++; n--;
        
        if(day % m == 0)
            n++;
    }
    
    printf("%d", day);
    
    return 0;
}

day로 하루하루 지나가게 하고 매일 양말 하나씩 신는다. m의 배수가 되면 양말 하나를 추가한다. 그리고 양말이 0이 되면 조건을 빠져나온다. 간단해!

 


이것도 문제 이해를 잘 못했음. 막 집합을 나눠서 버리라는 건 알겠는데 정확히 어떻게 하는 건지...? 항상 문제 이해하는데 10분정도 쓰는 것 같다ㅠ 어찌저찌 풀고 D까지 풀고 봤더니 문제 틀렸다고 떴었다. 확인해보니 오버플로우 때문이었다. 그래서 나중에 long long으로 바꿔서 풀었더니 맞았다. 

 

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
using i64 = long long;
 
int main() {
    int n;
    scanf("%d", &n);
    vector<int> v(n);
    
    for(int i = 0; i < n; i++)
        scanf("%d", &v[i]);
        
    sort(v.begin(), v.end());
    i64 sum = 0;
    for(int i = 2; i <= n; i++)
        sum += (i64)v[i-2]*(i64)i;
    sum += (i64)v[n-1]*(i64)n;
    
    printf("%lld", sum);
    
    return 0;
}

난 0번 * 2번 더하고 1번 * 3번 더하고 이렇게 생각했는데 전체 합을 구한 다음 전체 합 - v[0] -v[1] 이런 식으로 빼는 방법도 있었다ㅋㅋ 비슷하긴 한데 적어놔야지

 

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
using i64 = long long;
int main() {
    int n;
    scanf("%d", &n);
    
    vector<i64> v(n);
    i64 sum = 0;
    
    for(int i = 0; i < n; i++) {
        scanf("%lld", &v[i]);
        sum += v[i];
    }
    
    i64 ans = sum;
    sort(v.begin(), v.end());
    
    for(int i = 0; i < n - 1; i++){
        ans += sum;
        sum -= v[i];
    }
    
    printf("%lld", ans);
    
    return 0;
}

 

 


 

 

램프의 색을 연속되지 않게 바꾸는 문제이다. 단 색을 바꾸는 횟수를 최소한으로 해야한다. 그래서 바꾸는 경우를 다 설정한 다음 바꿔치기 했음. 연속 세 개일 때 중간의 하나를 바꾸는 걸 먼저 해야 최소가 될 것 같아서 이것부터 바꿨다. 하지만 틀렸다! 지금 생각해보니 저렇게 해도 최소가 아닌 경우가 있을 것 같아서 모든 경우 중 최소를 찾아야 할 것 같다. 

 

RRR일때 RBR로만 바꿨는데 RGR 경우도 생각해서 둘 중 최소만 구하기 같이.. 다시 푼다면 이렇게 해봐야겠다. 

 

dh... 생각해보니 항상 세개로만 짤랐는데 두개일 경우도 있구나

 

#include <iostream>
#include <string>
using namespace std;
 
int main() {
    int n;
    scanf("%d", &n);
    string s;
    cin >> s;
    
    int count = 0;
    
    for(int i = 0; i < n-2; i++){
        if(s[i] == s[i+1] && s[i+2] == s[i+1]){
            if(s[i] == 'B' || s[i] == 'G')
                s[i+1] = 'R';
            else
                 s[i+1] = 'B';
            count++;
        }
    }
    
    for(int i = 0; i < n-2; i++){
        string tmp = "";
        tmp += s[i]; tmp += s[i+1]; tmp += s[i+2];
        if(tmp=="RRB" || tmp=="BRR" || tmp=="RBB" || tmp=="BBR"){
            s[i+1] = 'G'; count++;}
        else if(tmp=="RRG" || tmp=="GRR" || tmp=="RGG" || tmp=="GGR"){
            s[i+1] = 'B'; count++;}
        else if(tmp=="GGB" || tmp=="BGG" || tmp=="BBG" || tmp=="GBB"){
            s[i+1] = 'R'; count++;}
    }
    
    for(int i = 0; i < n-1; i++){
        if(s[i] == s[i+1]){
            if(s[i] == 'B' || s[i] == 'G')
                s[i] = 'R';
            else
                 s[i] = 'B';
            count++;
        }
    }
    
    printf("%d\n", count);
    cout << s;
    
    return 0;
}

그래서 아래에 두개일 때를 추가해줬다. 코드가 구리다는 생각이 들긴 한데 괜찮다. 원래 맞으면 장땡이다. 

 

야호~~~~~

#include <iostream>
#include <string>
using namespace std;

int main()
{
	int n;
	string s;

	cin >> n >> s;

	int c = 0;
	string alpha = "RGB";

	for (int i = 0; i < n; i++)
	{
		char l = (i == 0) ? '.' : s[i - 1];
		char r = (i == n - 1) ? '.' : s[i + 1];

		if (s[i] != l)
			continue;

		c++;

		for (auto& a : alpha)
		{
			if (l == a || r == a)
				continue;

			s[i] = a;
			break;
		}
	}

	cout << c << '\n' << s << '\n';

	return 0;
}

dh.. gjf... 

바로 이해 안 돼서 적었다. 

 

오....

앞 뒤 문자 하나씩 가져온 다음 앞 뒤와 다 다르게 값을 끼워넣는다. 또 문자열 맨 처음과 끝을 비교할 때 앞에 문자는 임의로 넣어줘서 비교함.. 오.. 오... 신기하다...

 

저기서 auto는 파이썬에 리스트에서 값 빼오는 거랑 비슷한 것 같다. 잘은 모르겠다. 

 

암튼 신기하다.. 오... 

 


 

 

마지막으로 E번이다. 이 때 15분 정도가 남았었다. 그래서 풀지 말지 고민하다가 결국 틀린 문제 다시 보기로 했다. (C, D번 틀렸었음) 게다가 번역도 알아보기 힘들었었다. ㅎㄷ ㄷ 

 

 

음.. 다시 풀어볼려고 하니 문제 해석을 못하겠다. 뭔가 길이를 구해서 최소값을 구하라 하고 있는 것 같긴 한데 명확히 뭐라 하는 지는 모르겠는... 그래서 정 안되겠어서 너굴체로 번역해보려 하다가 현타와서 그냥 물어봤다. 

이제는 문제 이해는 했는데 풀지를 못하겠다ㅋㅋㅋ 백준에서 관련 문제 더 풀어보고 와야겠다. 


C, D번 중 C는 다시 풀어 맞췄고 D는 틀린채로 2시간이 지났다. 처음 코포 연습한 후기로는 두시간이 정말 빨랐었고 시간 배분을 잘해야 겠다.. 120 / 5 하면 한 문제에 24분정도 쓰면 되겠다. A는 쉬우니깐 빨리 풀어서 E 푸는데 시간 더 쓰고.. 휴 아무튼 재밌는 경험이었음