dp+优化。
dp方程很好想,f[i][j]表示走到第i个柱子高度为j的地方的能获得的最多柿子。
f[i][j]=max(f[i][j-1],f[k][j-d])+v[i][j] (k为任意一根柱子)
发现f[k][j-d]只和j-d有关,和哪根柱子无关,记录ma[h]表示h高度获得的最多柿子。
f[i][j]=max(f[i][j-1],ma[j-d])+v[i][j]
转移就变成O(1)的了。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cstdlib> using namespace std; int n,h,d,v[2005][2005],f[2005][2005],ma[2005]; int main() { scanf("%d%d%d",&n,&h,&d); for (int i=1;i<=n;i++) { int x,y; scanf("%d",&x); for (int j=1;j<=x;j++) scanf("%d",&y),v[i][y]++; } int ans=0; for (int i=1;i<=n;i++) for (int j=0;j<d;j++) f[i][h-j]=v[i][h-j]+f[i][h-j+1], ma[h-j]=max(ma[h-j],f[i][h-j]), ans=max(ans,f[i][h-j]); for (int now=h-d;now;now--) for (int i=1;i<=n;i++) f[i][now]=max(f[i][now+1],ma[now+d])+v[i][now], ma[now]=max(ma[now],f[i][now]), ans=max(f[i][now],ans); cout<<ans<<endl; return 0; }