P1107 [BJWC2008]雷涛的小猫
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]为当前爬的树为第
i
i
i棵树,在
j
j
j高度得到的柿子,可以得到递推式
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
]
[
j
−
1
]
,
d
p
[
k
]
[
j
−
d
e
l
]
)
dp[i][j]=max(dp[i][j-1],dp[k][j-del])
dp[i][j]=max(dp[i][j−1],dp[k][j−del])
因此可以写出代码
for(int j=1;j<=h;j++)
for(int i=1;i<=n;i++){
if(j>d)
for(int k=1;k<=n;k++){
if(k==i)continue;
ret=max(ret,f[k][j-d]);
}
f[i][j]=max(f[i][j-1],ret)+a[i][j];
}
for(int i=1;i<=n;i++)
ans=max(ans,f[i][h]);//还要再找一遍从阳台跳到哪个柱子最优
但是三个循环是不可以的,时间复杂度太高,需要进行优化,以高度为变量记录 d p [ k ] [ j − d e l ] dp[k][j-del] dp[k][j−del]的最大值 a n s [ h ] ans[h] ans[h]。
int f[2001][2001],a[2001][2001];
int ans[2001];
main(void)
{
int n=read();
int h=read();
int del=read();
for(int i=1;i<=n;i++)
{
int num=read();
for(int j=1;j<=num;j++)
{
int x=read();
a[i][x]++;
}
}
for(int j=1;j<=h;j++)
for(int i=1;i<=n;i++)
{
f[i][j]=f[i][j-1];
if(j>=del)f[i][j]=max(f[i][j],ans[j-del]);
f[i][j]+=a[i][j];
ans[j]=max(ans[j],f[i][j]);
}
cout<<ans[h];
}
f
[
i
]
[
j
]
=
∑
k
=
0
min
(
i
−
1
,
j
)
f
[
i
−
1
]
[
j
−
k
]
f\left[ i \right] \left[ j \right] =\sum_{k=0}^{\min \left( i-1,j \right)}{f\left[ i-1 \right] \left[ j-k \right]}
f[i][j]=k=0∑min(i−1,j)f[i−1][j−k]
转化为
f
[
i
]
[
j
]
=
∑
k
=
max
(
0
,
j
−
i
+
1
)
j
f
[
i
−
1
]
[
k
]
f\left[ i \right] \left[ j \right] =\sum_{k=\max \left( 0,j-i+1 \right)}^j{f\left[ i-1 \right] \left[ k \right]}
f[i][j]=k=max(0,j−i+1)∑jf[i−1][k]
设
s
u
m
sum
sum变量
s
u
m
=
∑
k
=
max
(
0
,
j
−
i
+
1
)
j
f
[
i
−
1
]
[
k
]
sum=\sum_{k=\max \left( 0,j-i+1 \right)}^j{f\left[ i-1 \right] \left[ k \right]}
sum=k=max(0,j−i+1)∑jf[i−1][k]