본문 바로가기
PS/BOJ

백준 6062 / C++

by jaehoonChoi 2022. 7. 21.

https://www.acmicpc.net/problem/6062

 

6062번: Mixed Up Cows

Each of Farmer John's N (4 <= N <= 16) cows has a unique serial number S_i (1 <= S_i <= 25,000). The cows are so proud of it that each one now wears her number in a gangsta manner engraved in large letters on a gold plate hung around her ample bovine neck.

www.acmicpc.net

 

[ 풀이 ]

 

수열 S의 모든 순열에 대해 인접한 차이가 k 초과인 것의 개수를 구하는 문제이다.

완전탐색은 16!*16 이므로 TLE이다. 

이런 문제는 이전상태를 이용할 수 있다. 현재 수열이 일부 구성되어있는 상태에서 아직 안쓴

인덱스를 방문해가며 값을 갱신해주면 되는데, 이런 경우 비트마스킹을 이용한 dp를 해주면 된다. 

dp[state][idx]를 현재 비트값이 state이고, 마지막으로 본 인덱스가 idx일 때 조건을 만족하는 수열의 개수라고 하자.

다음 값을 갱신할 때 인덱스는 아직 방문안한 인덱스 i를 방문해야 한다. 

방문 안한 모든 i에 대해 그 dp[state+1<<i ][i]를 모두 더해주면 된다. 

기저조건은 전부 방문했을 때, 즉 state=2^0+2^1+...+2^(n-1)=2^n-1 일 때 1을 출력해주면 된다. 

답은 처음에 어디부터 시작할지 정해줘야 하므로  go(1<<i, i)를 더해주면 된다. 

 

[ Code ] 

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int n, k, s[16];
ll dp[1 << 16][16];

ll go(int state, int idx) {
    if (state == (1 << n) - 1) return 1;
    ll& ret = dp[state][idx];
    if (ret != -1) return ret;
    ret = 0;
    for (int i = 0; i < n; i++) {
        if (state & (1 << i))continue;
        if (abs(s[i] - s[idx]) > k) {
            ret += go(state | (1 << i), i);
        }
    }
    return ret;
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    memset(dp, -1, sizeof(dp));
    cin >> n >> k;
    for (int i = 0; i < n; i++) cin >> s[i];
    ll ans = 0;
    for (int i = 0; i < n; i++) ans += go(1 << i, i);
    cout << ans << '\n';
}

 

'PS > BOJ' 카테고리의 다른 글

dp with 포함배제 원리  (0) 2022.08.01
백준 11066 / C++  (0) 2022.07.21
백준 1520 / C++  (0) 2022.07.21
백준 9251 / C++  (0) 2022.07.21
백준 10942 / C++  (0) 2022.07.21

댓글