Programming

[CF] Educational Round 95 (Div. 2) _ 200914

minigb 2021. 4. 13. 02:28

(2020년 9월 15일에 작성한 글입니다.)

 

 

Dashboard - Educational Codeforces Round 95 (Rated for Div. 2) - Codeforces

 

codeforces.com

이렇게 긴장감 없는 코포는 처음이었어.

A번 예제 output이 잘못 나와있어서

이해하려고 노력하다가 B로 넘어갔었는데

A번 문제 때문에 unrated 되었고

그래서 그냥 적당히 풀었다.

A.

ans = ((y + 1) * k - 1 + (x - 2)) / (x - 1) + k

(x - 2)를 더한 건 올림을 위함이다.

int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int T;
	ll x, y, k;
	ll ans;

	cin >> T;
	while (T--) {
		cin >> x >> y >> k;
		
		ans = ((y + 1) * k - 1 + x - 2) / (x - 1) + k;

		cout << ans << '\n';
	}
	return 0;
}

B.

문제 잘못 읽어서 제출 한 번을 낭비했다...

unlocked된 수들을 내림차순으로 bubble sort 하면 됨.

int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int T;
	int N;
	int i, j;

	cin >> T;
	while (T--) {
		cin >> N;
		vector<int> arr(N);
		vector<int> locked(N);
		for (i = 0; i < N; i++) {
			cin >> arr[i];
		}
		for (i = 0; i < N; i++) {
			cin >> locked[i];
		}

		for (i = 0; i < N; i++) {
			if (locked[i]) {
				continue;
			}
			for (j = i + 1; j < N; j++) {
				if (locked[j]) {
					continue;
				}
				if (arr[i] < arr[j]) {
					swap(arr[i], arr[j]);
				}
			}
		}

		for (i = 0; i < N; i++) {
			cout << arr[i] << ' ';
		}
		cout << '\n';
	}
	return 0;
}

C.

구현으로 풀었다.

ㅋㅋㅋㅋㅋㅋㅋㅋ

진짜 어이 없다. 이걸 구현으로 풀다니.

dp문제인데, dp인것 같다는 느낌은 받았었는데

점화식을 모르겠어서 그냥 구현했다.

 

친구 차례에 1이 있으면 그걸 먹을 수 밖에 없음.

만약 그 다음 것이 1이면, 나한테 넘기고,

만약 0이면...

여기서부터가 좀 웃긴데

그 뒤로 0이 몇개인지 센 다음에

0이 홀수개면 friend가 하나 먹고

짝수개면 넘어가는 방식으로 했다.

0이 홀수개면, friend가 하나 먹어야

그 뒤로 한 개씩 돌아가면서 먹을 때

맨 마지막 0이 friend한테 가고, 1이 나한테 온다.

근데 이때 zero 개수를 셀 때,

0이 시작될 때 마다 zero를 셌더니 시간초과가 났고

그래서 0을 뺄 때마다 zero--를 해줬더니 wa가 떠서

이유를 확인해보니까

친구가 처음 0을 만날 때 zero--를 안해줬고,

또, zero 개수를 세기 시작하는 걸 zero == 0일때로 했는데,

zero의 초기 설정이 zero = 0이기 때문에

만약 맨 처음이 0이라면 zero는 -1이 되고

그러면 if(zero == 0)을 통과 안 해서 zero 개수 구하는 게 실행이 안 된다.

그래서 if(zero <= 0)으로 바꿨더니 맞았다.

코드를, 가장 효율적으로, 깔끔하게 짜려고 괜히 고집 부리다가

가끔 이런 실수가 나오는 거 같다.

여기서도... 그냥 처음부터 if(zero <= 0)했으면 한 번에 맞았을 걸 말이야...

int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int T;
	int N;
	int cnt;
	bool me;
	int zero;
	int i, j;

	cin >> T;
	while (T--) {
		cin >> N;
		vector<int> arr(N);
		for (i = 0; i < N; i++) {
			cin >> arr[i];
		}

		cnt = 0;
		me = false;
		zero = 0;
		for (i = 0; i < N;) {
			if (!me) {
				if (arr[i++] == 1) {
					cnt++;
				}
				else {
					zero--;
				}

				if (i < N && arr[i] == 0) {
					if (zero <= 0) {
						for (j = i + 1; j < N && arr[j] == 0; j++);
						zero = j - i;
					}

					if (zero % 2 == 1) {
						i++;
						zero--;
					}
				}
			}
			else {
				if (arr[i++] == 0) {
					zero--;
				}
				
				if (i < N && arr[i] == 1) {
					i++;
				}
			}

			me = !me;
		}

		cout << cnt << '\n';
	}
	return 0;
}

 

근데 문제는! 이렇게 풀면 안 된다는거

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

효규가 dp로 풀었다고 했는데

dp[1][0] = arr[0];
dp[1][1] = arr[0] + arr[1];
dp[0][1] = dp[1][0];

for (int i = 2; i < n; i++) {
  dp[i][0] = min(dp[i - 1][1], dp[i - 2][1]);
  dp[i][1] = min(dp[i - 1][0] + arr[i], dp[i - 2][0] + arr[i] + arr[i - 1]);
}

dp[x][0]는 x번째를 내가 가져갔을 때의 최솟값,

dp[x][1]는 x번째를 친구가 가져갔을 때의 최솟값.

근데 내가 처음에 궁금했던 건

이렇게 하면, 연속으로 최대 두 개만 뽑을 수 있다는 부분은 어떻게 체크되는거지?

였는데

점화식을 보면 바로 전 거랑, 2개 전 거를 상대방이 뽑았을 경우를 이용해서 min 값을 구하니까

이 풀이가 맞다.