題解
設有 \(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;
}