开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情
题目:小猫可以从宿舍的阳台上跳到窗外任意一棵柿子树的树顶。之后,她每次都可以在当前位置沿着当前所在的柿子树向下跳 1 单位距离。当然,小猫的能力远不止如此,她还可以在树之间跳跃。每次她都可以从当前这棵树跳到另外的任意一棵,在这个过程中,她的高度会下降 Delta 单位距离。每个时刻,只要她所在的位置有柿子,她就可以吃掉。整个“吃柿子行动”一直到小猫落到地面上为止。
雷涛调查了所有柿子树上柿子的生长情况。他很想知道,小猫从阳台出发,最多能吃到多少柿子?他知道写一个程序可以很容易的解决这个问题,但是他现在懒于写任何代码。于是,现在你的任务就是帮助雷涛写一个这样的程序。
思路:设f[i][j]表示高度为i在第j棵树上所能吃到的最多的柿子数,tx[i][j]高度为i在第j棵树上的柿子数,g[i]是高度为i最多可以吃多少柿子,那么转移方程就是
#include<bits/stdc++.h>
//#pragma-GCC-optimize("-Ofast");
#define ll long long
//#define int long long
#define lowbit(x) ((x)&(-x))
#define endl '\n'
using namespace std;
const ll mod=998244353;
const ll inf=1e9;
const double pi=acos(-1);
const int N=1e6+100;
ll qpow(ll a,ll b)
{
ll res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
int n,h,d,f[2005][5005],g[2005],tx[2005][5005];
signed main()
{
//ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>h>>d;
memset(tx,0,sizeof(tx));
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
for(int j=1;j<=n;j++){
int m;cin>>m;
for(int i=1;i<=m;i++){
int x;cin>>x;
tx[x][j]++;
}
}
for(int i=1;i<=h;i++){
for(int j=1;j<=n;j++){
f[i][j]=max(f[i][j],f[i-1][j]+tx[i][j]);
if(i>=d) f[i][j]=max(f[i][j],g[i-d]+tx[i][j]);
g[i]=max(g[i],f[i][j]);
//cout<<"f[i]="<<f[i][j]<<" f[i-1]="<<f[i-1][j]<<" g[i]="<<g[i]<<" tx[i][j]="<<tx[i][j]<<" i="<<i<<" j="<<j<<endl;
}
}
int ans=0;
for(int i=1;i<=n;i++) ans=max(ans,f[h][i]);
cout<<ans<<endl;
return 0;
}