본문 바로가기

BOJ

[BOJ 8903] 장비

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

 

8903번: 장비

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 N과 K가 주어진다. (1 ≤ N ≤ 10,000, 1 ≤ K ≤ N) 다음 N개 줄에는 0보다 크거나 같고, 10,000보다 작거나 같은 정수 다

www.acmicpc.net

Tag : case work

 

문제요약

장비마다 5개의 능력치가 있는데 장비를 여러개 골랐을 때 각각의 능력치는 고른 장비들에서 최대 하나로만 결정된다.

고를 수 있는 장비의 개수가 주어졌을 때 능력치 합의 최대를 구하라.

 

풀이

5개 이상 고를 수 있다면 각각의 능력치가 최대인 것을 하나씩 골라오면 된다.

그게 아니라면 \(O(2^{10} \times N)\) 비트마스킹 dp를 돌리면된다.

 

전체코드

#include "bits/stdc++.h"
#define endl '\n'

using namespace std;
using ll = long long;

#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
template<typename T>
struct FASTIO {
    char *p,O[2000000],*d;
    void set() {
        struct stat st;fstat(0, &st);d=O;
        p=(char*)mmap(0,st.st_size,1,1,0,0);
    }
    ~FASTIO() {
        write(1,O,d-O);
    }
    inline T get() {
        T x=0;bool e;p+=e=*p=='-';
        for(char c=*p++;c&16;x=10*x+(c&15),c=*p++);
        return e?-x:x;
    }
    inline void put(int x) {
        if(x<0) *d++='-', x=-x;
        char t[16],*q=t;
        do *q++=x%10|48; while(x/=10);
        do *d++=*--q; while(q!=t);
        *d++=10;
    }
};

FASTIO<int> IO;

void solve() {
    int n = IO.get(), k = IO.get();
    vector<vector<int>> v(n);
    for(int i=0; i<n; i++) {
        v[i].resize(5);
        for(auto &j : v[i]) j = IO.get();
    }
    if(k >= 5) {
        int mx[5] = {0, 0, 0, 0, 0};
        for(int i=0; i<n; i++) {
            for(int j=0; j<5; j++) mx[j] = max(mx[j], v[i][j]);
        }
        IO.put(accumulate(mx, mx + 5, 0));
        return;
    }
    vector<vector<int>> dp(32, vector<int>(6));
    for(int i=0; i<n; i++) {
        vector<int> t(32);
        for(int j=0; j<32; j++) {
            for(int p=0; p<5; p++) if(j & (1 << p)) t[j] += v[i][p];
        }
        for(int cnt=1; cnt<=5; cnt++) {
            for(int j=0; j<32; j++) {
                for(int p=31-j; p>=0; p=(p-1)&(31-j)) {
                    dp[j | p][cnt] = max(dp[j | p][cnt], dp[p][cnt - 1] + t[j]);
                    if(p == 0) break;
                }
            }
        }
    }
    int ans = 0;
    for(int i=0; i<32; i++) ans = max(ans, dp[i][k]);
    IO.put(ans);
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    //freopen("input.txt", "r", stdin);

    IO.set();
    int TC = IO.get();
    while(TC--) {
        solve();
    }
}

'BOJ' 카테고리의 다른 글

[BOJ 1725] 히스토그램  (1) 2022.01.22
[BOJ 2042] 구간 합 구하기  (0) 2022.01.18
[BOJ 16474] 이상한 전깃줄  (0) 2022.01.13
[BOJ 23578] 비 오는 날  (0) 2022.01.13
[BOJ 10523] 직선 찾기  (0) 2022.01.11