[动态规划] Codeforces 1348E Phoenix and Berries
Posted aemshana
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[动态规划] Codeforces 1348E Phoenix and Berries相关的知识,希望对你有一定的参考价值。
题解
设有 (n) 棵梅树,每个篮子的容量为 (k),第 (i) 棵树上的红梅数量为 (a_i),第 (i) 棵树上的蓝莓数量为 (b_i)。注意到最多只有 (n) 个篮子里面装的梅子是不同色的(如果从同一棵树上装了多个不同色的篮子,我们一定可以把这多个不同色的蓝子转化为多个同色的篮子加上一个不同色的篮子)。
设 (dp[i-1][j]) 表示前 (i-1) 棵树装完梅子后,剩下 (j) 个红梅,最多能填满的篮子的数量。令 (sum=sumlimits_{p=1}^{i-1}(a_p+b_p)-dp[i-1][j] imes 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]=maxleft{dp[i][(j-s+a_i) mod k],dp[i-1][j]+1+leftlfloorfrac{j-s+a_i}{k} ight floor + leftlfloorfrac{sum-j-k+s+b_i}{k} ight floor ight})
时间复杂度 (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
",Ans);
return 0;
}
以上是关于[动态规划] Codeforces 1348E Phoenix and Berries的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces-546D Soldier and Number Game 筛法+动态规划
Codeforces 830D Singer House 动态规划
如何使用动态规划自顶向下方法解决这个 problem?
Codeforces 837D Round Subset - 动态规划 - 数论