Code Jam - Google’s Coding Competitions
Put your coding skills to the test as you work your way through multiple rounds of algorithmic coding puzzles for the title of Code Jam Champ and 15,000 USD.
codingcompetitions.withgoogle.com
문제 A: 다시 우주를 구하기 (Saving The Universe Again)
↓ 문제 캡처
간략한 문제 해설
공격(Shoot)과 기 모으기(Charge)가 있다고 했을 때,
Charge 시 데미지가 2배가 되어 공격력이 높아지고, Shoot 시 높아진 공격력으로 맞게 된다. 초기 데미지는 1이다.
예를 들어 'CS'의 총 데미지는 2, 'SCCSSC'의 총 데미지는 1+4+4 = 9가 된다.
이 때 맞는 데미지를 낮추기 위해 인접한 C와 S를 바꿀 수 있고, 실드가 버틸 수 있는 한계치 D가 주어진다.
그러므로 C와 S를 최소한으로 바꾸어서 D와 같거나 더 낮은 데미지를 만들어야 한다.
입력에서 한계치 D와 공격패턴이 주어지므로, 데미지를 D와 같거나 더 작게 만드는 최소한의 패턴 변경수를 출력하면 된다.
만약 패턴을 바꿔도 그런 경우를 만들 수 없다면 'IMPOSSIBLE'을 출력한다.
핵심 알고리즘
처음에 각 S에서의 데미지를 저장하고, 총 교체 가능 횟수만큼 제일 큰 숫자를 2로 나누면 된다.
각 S에서 보면 왼쪽에 있는 C의 개수만큼 자리를 바꿀 수 있으므로, 총 교체 가능 횟수는 각 S의 교체 가능횟수의 합이 된다.
총 교체 가능 횟수가 소진될 때까지 데미지를 나누고, D와 같거나 작아지는 순간에 교체한 횟수를 출력하면 된다.
예시) 6 SCCSSC
데미지
SCCSSC
1 44
교체가능횟수
SCCSSC
22
(∵ 총 교체가능횟수 4)
데미지 정렬 → 144
가장 큰 숫자 2로 나누기 → 1번 나누고 정렬하면 124 (총합 7) → 2번 나누고 정렬하면 122 (총합 5 => 2 출력 후 종료)
이를 적용해 코드를 짜면 된다.
내 코드
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int t, d;
string p;
scanf("%d", &t);
for(int i=1; i<=t; i++) {
cin >> d >> p;
int cntC = 0, counts = 0, damage = 1;
vector<int> shoot;
int len = p.length();
// 각 S마다 왼쪽에 있는 C의 개수만큼 교체 가능
for(int j=0; j<len; j++) {
if (p[j]=='C') {
damage *= 2;
cntC++;
} else {
shoot.push_back(damage);
counts += cntC;
}
}
// 데미지 총합이 D와 같거나 작아질때까지
// 교체가능횟수 소진될 때까지 shoot에 들어있는 가장 큰 damage를 2로 나누기
int vlen = shoot.size(), sum = 0;
for(int j=0; j<vlen; j++) {
sum += shoot[j];
}
int changed = 0;
while(counts-- && sum > d) {
sort(shoot.begin(), shoot.end());
shoot[vlen-1] /= 2;
sum -= shoot[vlen-1];
changed++;
}
if (sum > d) printf("Case #%d: IMPOSSIBLE\n", i);
else printf("Case #%d: %d\n", i, changed);
}
return 0;
}
다른 사람 코드
정렬을 내림차순으로 정렬해 앞에서 꺼내썼다.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> shoot;
bool compare(int a, int b) {
return a > b;
}
int main() {
int tc, t = 0;
cin >> tc;
while(t++ != tc) {
cout << "Case #" << t << ": ";
int d, counts = 1, damageSum = 0, cnt = 0, damage = 1;
string p;
cin >> d >> p;
shoot.clear();
for(int i=0; i<p.size(); i++) {
if(p[i] == 'C') {
damage *= 2, cnt++;
} else {
counts += cnt, damageSum += damage;
shoot.push_back(damage);
}
}
bool find = false;
int i=0;
while(counts--) {
if(damageSum <= d) {
find = true;
cout << i << '\n';
break;
}
sort(shoot.begin(), shoot.end(), compare);
damageSum -= shoot[0] / 2;
shoot[0] /= 2;
i++;
}
if(!find) cout << "IMPOSSIBLE" << '\n';
}
return 0;
}
'[C_C++]코딩테스트 연습 > 기타' 카테고리의 다른 글
[그리디 문제풀기] Google Code Jam 2018 - Qualification Round (문제 B) (C/C++) (0) | 2022.08.25 |
---|