21.01.11 12:30 virtual 참가 (1시간 20분) / performance = 1816
A. Restoring Three Numbers (*800)
입력으로 a+b, a+c, b+c, a+b+c가 랜덤 순서로 들어온다.
이를 다 더하면 3(a+b+c) 이므로, a+b+c의 값을 구해줄 수 있다.
따라서 구한 a+b+c의 값과 동일한 입력을 찾은 뒤, 해당 입력에서 나머지 세 입력을 빼주면 각각 a,b,c가 나온다.
[소스 코드]
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main(void) {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
ll a, b, c, d; cin >> a >> b >> c >> d;
ll total = a + b + c + d;
total /= 3;
if (a == total) {
cout << a - b << ' ' << a - c << ' ' << a - d;
}
else if (b == total) {
cout << b - a << ' ' << b - c << ' ' << b - d;
}
else if (c == total) {
cout << c - a << ' ' << c - b << ' ' << c - d;
}
else cout << d - a << ' ' << d - b << ' ' << d - c;
}
B. Make Them Equal (*1200)
어떤 음이 아닌 정수 D로 배열의 각 원소를 더하거나, 빼거나, 그대로 둘 때 모든 원소를 동일하게 만들 수 있다면 그 가능한 D중 최솟값을 찾는 문제이다.
배열의 원소들의 범위가 작으므로 완전탐색으로 배열의 원소가 k로 같다면 이를 만들 수 있는 D가 존재하는지를 찾는다.
[소스 코드]
#include<bits/stdc++.h>
#define ini(x, y) memset(x, y, sizeof(x));
using namespace std;
int A[101];
int cnt[301];
int main(void) {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int n; cin >> n;
int ans = 100000;
for (int i = 1; i <= n; i++) cin >> A[i];
for (int i = -100; i <= 200; i++) {
ini(cnt, 0);
for (int j = 1; j <= n; j++) {
cnt[abs(A[j] - i)]++;
}
int k = 0;
for (int i = 1; i <= 300; i++) {
if (cnt[i] > 0) k++;
}
if (k <= 1) {
int tmp = 0;
for (int j = 1; j <= n; j++) {
tmp = max(tmp, abs(A[j] - i));
}
ans = min(ans, tmp);
}
}
if (ans == 100000) cout << -1;
else cout << ans;
}
C. Gourmet Cat (*1400)
월/목/일요일에는 fish를, 화/토요일에는 rabbit을, 수/금요일에는 chicken을 먹고,
fish는 a개, rabbit은 b개, chicken은 c개 있을 때, 가장 오래 먹을 수 있도록 요일을 고르는 문제이다.
어떤 요일부터 시작하든, 항상 7일동안은 fish를 3개, rabbit과 chicken을 2개씩 먹는다.
따라서 최소 min(a/3, b/2, c/2) * 7일 만큼은 먹을 수 있고, 나머지를 가지고 얼마나 더 먹을 수 있는지 확인한다.
a, b, c중 적어도 하나는 1이하의 값이 되므로 직접 다 돌려보면 된다.
[소스 코드]
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int A[7] = { 1, 2, 3, 1, 3, 2, 1 };
int main(void) {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
ll a, b, c; cin >> a >> b >> c;
ll ans = 0;
ll k = min({ a / 3, b / 2, c / 2 });
a -= k * 3;
b -= k * 2;
c -= k * 2;
for (int i = 0; i < 7; i++) {
ll ta = a;
ll tb = b;
ll tc = c;
ll cnt = 0;
for (int j = i; ; j++) {
if (A[j % 7] == 1) {
if (ta == 0) break;
else cnt++, ta--;
}
else if (A[j % 7] == 2) {
if (tb == 0) break;
else cnt++, tb--;
}
else {
if (tc == 0) break;
else cnt++, tc--;
}
}
ans = max(ans, k * 7 + cnt);
}
cout << ans;
}
D. Walking Robot (*1500)
battery와 accumulator의 최대 용량이 각각 b, a이고, 시작할 때는 최대만큼 채워져있다.
1인 구간을 지나갈 때에 만약 battery를 이용한다면 accumulator의 용량은 1 증가한다. 최대 용량을 넘지는 못한다.
0인 구간은 감소하기만 한다.
따라서, 1인 구간을 지나갈 때, accumulator의 용량이 꽉차있지 않고 battery를 이용할 수 있다면 무조건 battery를 이용하는게 이득이고, 0인 구간을 지나갈 땐 최대한 accumulator를 이용하는게 이득이다.
[소스 코드]
#include<bits/stdc++.h>
using namespace std;
int s[200001];
int main(void) {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int n, b, a; cin >> n >> b >> a;
int nowa = a;
int nowb = b;
for (int i = 1; i <= n; i++) cin >> s[i];
for (int i = 1; i <= n; i++) {
if (s[i] == 1) {
if (nowb > 0) {
if (nowa == a) nowa--;
else {
nowb--;
nowa++;
}
}
else if (nowa > 0) nowa--;
else return cout << i - 1, 0;
}
else {
if (nowa > 0) nowa--;
else if (nowb > 0) nowb--;
else return cout << i - 1, 0;
}
}
cout << n;
}
E. Two Teams (*1800)
두 코치가 서로 번갈아가면서 선수들을 뽑아가는데, 현재 남은 선수 중 제일 높은 선수를 뽑는다.
그리고 그 선수 양옆으로 남은 선수들 중 각각 k명씩 데리고 간다. 만약 k명이 없다면 있는 만큼만 뽑아간다.
먼저, 선수들의 능력치와 위치를 priority_queue에 저장하여 매번 제일 높은 선수를 확인하도록 한다.
그리고, 현재 선수를 기준으로 왼쪽에 있는 선수와 오른쪽에 있는 선수를 저장해두고, 선수를 뽑아갈 때마다
좌우의 선수를 갱신시켜준다.
[소스 코드]
#include<bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
int L[200010], R[200010];
int A[200010];
int ans[200010];
int main(void) {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int n, k; cin >> n >> k;
priority_queue<pii> pq;
for (int i = 1; i <= n; i++) {
L[i] = i - 1;
R[i] = i + 1;
cin >> A[i];
pq.push({ A[i], i });
}
R[n + 1] = n + 1;
int turn = 1;
while (!pq.empty()) {
pii p = pq.top(); pq.pop();
if (A[p.second] == -1) continue;
ans[p.second] = turn;
A[p.second] = -1;
vector<int> tmp;
int cnt = 0;
int idx = p.second;
while (1) {
idx = L[idx];
if (idx == 0) break;
tmp.push_back(idx);
if (A[idx] == -1) continue;
else {
A[idx] = -1;
ans[idx] = turn;
cnt++;
}
if (cnt == k || idx == 0) break;
}
idx = L[idx];
for (int i : tmp) L[i] = idx;
tmp.clear();
cnt = 0;
idx = p.second;
while (1) {
idx = R[idx];
if (idx == n + 1) break;
tmp.push_back(idx);
if (A[idx] == -1) continue;
else {
A[idx] = -1;
ans[idx] = turn;
cnt++;
}
if (cnt == k || idx == n + 1) break;
}
idx = R[idx];
for (int i : tmp) R[i] = idx;
if (turn == 1) turn = 2;
else turn = 1;
}
for (int i = 1; i <= n; i++) cout << ans[i];
}
이 문제를 set으로도 풀 수 있다.
set이 자동으로 정렬해주므로, 굳이 양쪽의 원소가 무엇인지 갱신시켜줄 필요가 없다.
set의 유용성을 많이 느끼게 해주는 문제이다.
[소스 코드]
#include<bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
int ans[200001];
int main(void) {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int n, k; cin >> n >> k;
set<int> s;
priority_queue<pii> pq;
for (int i = 1; i <= n; i++) {
int a; cin >> a;
s.insert(i);
pq.push({ a, i });
}
int turn = 1;
while (!pq.empty()) {
pii p = pq.top(); pq.pop();
auto it = s.lower_bound(p.second);
if (it == s.end() || *it != p.second) continue;
ans[p.second] = turn;
s.erase(it);
for (int i = 1; i <= k; i++) {
auto left = s.lower_bound(p.second);
if (left == s.begin()) break;
left--;
ans[*left] = turn;
s.erase(left);
}
for (int i = 1; i <= k; i++) {
auto right = s.lower_bound(p.second);
if (right == s.end()) break;
ans[*right] = turn;
s.erase(right);
}
if (turn == 1) turn = 2;
else turn = 1;
}
for (int i = 1; i <= n; i++) cout << ans[i];
}
'프로그래밍 대회 풀이 > Codeforces' 카테고리의 다른 글
[Codeforces] Round #559 (Div. 2) A ~ E 풀이 (0) | 2021.03.07 |
---|---|
[Codeforces] Educational Round 102 A ~ E 풀이 (0) | 2021.01.20 |
[Codeforces] Round #694 (Div. 2) 풀이 (0) | 2021.01.07 |
[Codeforces] Round #551 (Div. 2) A ~ D 풀이 (2) | 2021.01.04 |
[Codeforces] Educational Round 76 (A ~ E) 풀이 (2) | 2021.01.03 |