제출 #1362930

#제출 시각아이디문제언어결과실행 시간메모리
1362930yyc000123IMO (EGOI25_imo)C++20
100 / 100
4499 ms889712 KiB
#include<bits/stdc++.h>
using namespace std ;
#define g0 get<0>
#define g1 get<1>
#define g2 get<2>
const int N = 2e4+5 ;
const int M = 105 ;
const int K = 105 ;
int n , m , k , arr[N][M] , f[N][M*K] , g[M][M*K] , h[M][M*K] ;
// f[i][j] = 第i個人,分數上界j,最少要公開多少個
// g[i][j] = 對於當前的人,有i個不公開,公開分數總和(分數下界)為j是否合適
vector<tuple<int,int,vector<int>>> vt ;

int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0) ;
    cin >> n >> m >> k ;
    vt.resize(n) ;
    for(int i=0 ; i<n ; i++){
        g1(vt[i]) = -i ; g2(vt[i]).resize(m) ;
        for(int j=0 ; j<m ; j++) cin >> g2(vt[i])[j] , g0(vt[i])+=g2(vt[i])[j] ;
        // sort(g2(vt[i]).begin(),g2(vt[i]).end()) ;
    }
    sort(vt.begin(),vt.end()) ;
    for(int i=0 ; i<n ; i++){
        for(int j=0 ; j<m ; j++) arr[i+1][j+1] = g2(vt[i])[j] ;
    }
    memset(f,0x3f,sizeof(f)) ;
    memset(f[0],0,sizeof(f[0])) ;
    for(int i=1 ; i<=n ; i++){
        int limit = m ;
        if(1<i && i<n) limit = min(limit,(g0(vt[i])-g0(vt[i-2]))/k) ;
        if(limit){
            memset(g,0,sizeof(g)) ; g[0][0] = 1 ;
            for(int j=1 ; j<=m ; j++){
                memset(h,0,sizeof(h)) ;
                for(int l=0 ; l<=limit ; l++){
                    for(int s=0 ; s<=m*k ; s++){
                        if(l) h[l][s]|=g[l-1][s] ; // hide j
                        if(s-arr[i][j]>=0) h[l][s]|=g[l][s-arr[i][j]] ;
                    }
                }
                memcpy(g,h,sizeof(g)) ;
            }
            for(int l=0 ; l<=limit ; l++){
                for(int s=0 ; s<=m*k ; s++){
                    if(!g[l][s] || s+l*k>m*k) continue ;
                    int temp = s ;
                    if(i!=1 && -g1(vt[i-2])<-g1(vt[i-1])) temp-- ;
                    if(temp>=0) f[i][s+l*k]=min(f[i][s+l*k],f[i-1][temp]+m-l) ;
                }
            }
        }
        else{
            int temp = 0 ;
            if(i!=1 && -g1(vt[i-2])<-g1(vt[i-1])) temp = 1 ;
            f[i][g0(vt[i-1])] = f[i-1][g0(vt[i-1])-temp]+m ;
        }
        for(int j=1 ; j<=m*k ; j++) f[i][j]=min(f[i][j],f[i][j-1]) ;
    }
    cout << f[n][m*k] << '\n' ;
    return 0 ;
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…