题目
参考
题意:给定
n
n
n棵树,每棵树有
a
i
a_i
ai个红果子,
b
i
b_i
bi个蓝果子,给定篮子大小为
k
k
k,同一棵树的果子,或者同种颜色的果子,可以放在同一篮子。问最多可以装满多少大小为
k
k
k的篮子。
1
<
=
n
,
k
<
=
500
,
0
<
=
a
i
,
b
i
<
=
1
e
9
1<=n,k<=500,0<=a_i,b_i<=1e9
1<=n,k<=500,0<=ai,bi<=1e9
题解:根据数据范围,我们可以发现混合色篮子数,相对纯色篮子数,要少的多,混合色篮子,最多可以保持
n
n
n个,因为同一棵树上的果子,如果混合色篮子超过1个,我们完全可以把他分成若干个纯色篮子。
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示当前到第
i
i
i棵树时,红色苹果数剩下
j
j
j个时,能得到的最大篮子数,剩下的蓝色苹果数可以由剩下的红色苹果数推算出来
b
=
s
u
m
−
d
p
[
i
]
[
j
]
−
j
b=sum-dp[i][j]-j
b=sum−dp[i][j]−j,我们根据当前的
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j],枚举下一棵树用来凑混合篮子的红色苹果数
r
r
r,就可以推出下一颗树其对应的剩余红色苹果数的最大篮子树,如下
int b2 = b + blue[i] - (k-r);
int r2 = j + red[i] - r;
dp[i][r2%k] = max(dp[i][r2%k],dp[i][j]+b2/k+r2/k+1);
注意考虑下一棵树,不凑混合篮子的情况
int b2 = b + blue[i];
int r2 = j + red[i];
dp[i][r2%k] = max(dp[i][r2%k],dp[i][j]+b2/k+r2/k);
最后答案就是
m
a
x
(
d
p
[
n
]
[
i
]
)
max(dp[n][i])
max(dp[n][i]),由于
d
p
dp
dp转移时只与上一层有关,还可以进一步空间优化。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 510;
ll dp[maxn][maxn];
int red[maxn],blue[maxn];
int n,k;
int main() {
scanf("%d%d",&n,&k);
for(int i = 1;i <= n;++i) {
scanf("%d%d",&red[i],&blue[i]);
}
memset(dp,-1,sizeof(dp));
dp[0][0] = 0;
ll sum = 0;
for(int i = 1;i <= n;++i) {
for(int j = 0;j < k;++j) {
if(dp[i-1][j] != -1) {
int b = sum - dp[i-1][j]*k - j;
for(int r = max(1,k-blue[i]);r < k && r <= red[i];++r) {
int b2 = b + blue[i] - (k-r);
int r2 = j + red[i] - r;
dp[i][r2%k] = max(dp[i][r2%k],dp[i-1][j]+b2/k+r2/k+1);
}
int b2 = b + blue[i];
int r2 = j + red[i];
dp[i][r2%k] = max(dp[i][r2%k],dp[i-1][j]+b2/k+r2/k);
}
}
sum += red[i]+blue[i];
}
ll ans = 0;
for(int i = 0;i < k;++i)
ans = max(ans,dp[n][i]);
printf("%I64d\n",ans);
}