본문 바로가기

알고리즘

Boj 25379 c++ 피하자

그리디는 여전히 어렵다. 이번에도 결국 구글링을 하였다.

수많은 시도들...

 

 

 

입력으로 N개의 숫자가 배열의 형태로 주어질 때, 두 수의 자리를 바꾸어 홀수와 짝수가 인접한 횟수가 1회가 되도록 정렬할 때, 두 수를 교환하는 최소 횟수를 구하는 것이 문제이다.

 

문제 풀이의 핵심은 횟수를 구하는 최적의 방법을 생각하는 것과, 교환 횟수가 계산되는 매커니즘을 이해하는 것에 있었다.

 

짝수나 홀수를 한 끝으로 모는 횟수를 계산하는 방법은 다음과 같다.

만약 홀수를 한쪽으로 정렬한다고 생각하면 짝수가 이전에 등장한 횟수만큼 원래의 총 횟수에 누적해 더해주어야 한다.

*이유가 뭘까?

왼쪽을 기준으로 생각하면 하나의 홀수 이전에 등장한 짝수를 모두 오른쪽으로 빼내어주어야 좌-홀수 우-짝수의 형태가 되기 때문이다. 이는 짝수의 경우에도 마찬가지이다. 때문에, 두 경우중에서 더 최적인 것을 출력해주면 된다.

사진에서도 마찬가지로 짝홀짝홀의 형태로 입력이 주어진 경우를 홀수 정렬, 짝수 정렬 두가지로 생각해보자.

 

case1. 짝수 정렬: 짝수 등장. 그전에 홀수가 등장한 횟수를 더해준다.

1+2=3

case2. 홀수 정렬: 홀수 등장. 그전에 짝수가 등장한 횟수를 더해준다. 

1+1=2

3>2

정답: 2

 

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

int main(){

   int N, odd_cnt=0, even_cnt=0;
   long long ans1=0, ans2=0;

   cin>>N;

   vector<int>v(N);

   for(int i=0; i<N; i++){
    cin>>v[i];
   }
   for(int i=0; i<N; i++){
    if(v[i]%2==0){
        even_cnt++;
        ans1+=odd_cnt;//짝수정렬
    }
    else{
        odd_cnt++;
        ans2+=even_cnt;//홀수정렬
    }
   }
   long long res=(ans1>=ans2)?ans2:ans1;
   cout<<res;
}

'알고리즘' 카테고리의 다른 글

Boj 21758 c++ 꿀따기  (0) 2025.06.03
Boj 31964 c++ 반품회수  (0) 2025.06.02
Boj 1967 & 19581 c++ 트리의 지름 + 두 번째 지름  (0) 2025.06.01
Boj 19940 c++ 피자오븐  (0) 2025.06.01
Boj 31963 c++ 두배  (0) 2025.06.01