[动态规划] Codeforces 1348E Phoenix and Berries

题解

设有 \(n\) 棵梅树,每个篮子的容量为 \(k\),第 \(i\) 棵树上的红梅数量为 \(a_i\),第 \(i\) 棵树上的蓝莓数量为 \(b_i\)。注意到最多只有 \(n\) 个篮子里面装的梅子是不同色的(如果从同一棵树上装了多个不同色的篮子,我们一定可以把这多个不同色的蓝子转化为多个同色的篮子加上一个不同色的篮子)。

\(dp[i-1][j]\) 表示前 \(i-1\) 棵树装完梅子后,剩下 \(j\) 个红梅,最多能填满的篮子的数量。令 \(sum=\sum\limits_{p=1}^{i-1}(a_p+b_p)-dp[i-1][j]\times k\),则剩下的蓝莓数量等于 \(sum-j\)

枚举第 \(i\) 棵树生成的不同色的篮子的组成,设不同色的篮子使用红梅 \(s\) 个,使用蓝莓 \(k-s\) 个。则前 \(i\) 棵树所剩的红梅还有 \(j-s+a_i\) 个,蓝莓还有 \(sum-j-k+s+b_i\) 个。

\(dp[i][(j-s+a_i) \mod k]=max\left\{dp[i][(j-s+a_i) \mod k],dp[i-1][j]+1+\left\lfloor\frac{j-s+a_i}{k} \right\rfloor + \left\lfloor\frac{sum-j-k+s+b_i}{k} \right\rfloor\right\}\)

时间复杂度 \(O(NK^2)\) 。好像需要稍微卡一下才能过= =。

Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;

#define RG register int
#define LL long long

template<typename elemType>
inline void Read(elemType &T){
    elemType X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    T=(w?-X:X);
}

int a[505],b[505];
LL Sum[505],dp[505][505];
bool exist[505][505];
int N,K;

int main(){
    Read(N);Read(K);
    exist[0][0]=true;
    RG i,j,temp,p,l,r,s;
    LL sum;
    for(i=1;i<=N;++i){
        Read(a[i]);Read(b[i]);
        Sum[i]=Sum[i-1]+a[i]+b[i];
        for(j=0;j<K;++j){
            sum=Sum[i-1]-dp[i-1][j]*(LL)K;
            if(!exist[i-1][j]) continue;
            temp=(j+a[i])%K;
            dp[i][temp]=dp[i-1][j]+(j+a[i])/K+(sum-(LL)j+(LL)b[i])/(LL)K;
            exist[i][temp]=true;
            l=max(0,K-b[i]),r=min(a[i],K);
            for(s=l;s<=r;++s){
                p=(j-s+a[i])%K;
                dp[i][p]=max(dp[i][p],dp[i-1][j]+1LL+(j-s+a[i])/K+(sum-j-K+s+b[i])/K);
                exist[i][p]=true;
            }
        }
    }
    LL Ans=0;
    for(i=0;i<K;++i)
        Ans=max(Ans,dp[N][i]);
    printf("%I64d\n",Ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AEMShana/p/12818773.html