感觉是一道很有意思的DP题目。
题目的状态方程并不难推(毕竟题目就两个有用信息量啊)
dp[i][j] 表示第i颗树 高度为j时的 最大柿子数目。
一开始转移方程推错了,后来仔细思考才发现 自己果然是菜啊~
因为可以从一棵树跳到任意一棵树 所以 这一步需要思考搞
再处理一下 从这颗树j高度到j-1高度就可以了


#include <cstdio> #include <algorithm> #include <cstring> using std::max; int n,h,Down; int Tree[3555][2222]; int dp[3555][6666]; inline int Read(){ int ans = 0 , flag = 1; char ch = getchar() ; while(ch > '9' || ch < '0'){ if(ch == '-') flag = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ ans = ans * 10 + ch - '0'; ch = getchar(); } return flag * ans; } int main(){ n = Read(); h = Read(); Down = Read(); for(int i=1;i<=n;++i){ int x = Read(); for(int j=1;j<=x;++j){ int y = Read(); Tree[i][y]++; } } for(int j=h;j>=0;j--){ int MAX = 0; for(int i=1;i<=n;i++){ MAX = max(MAX,dp[i][j+Down]); } for(int i=1;i<=n;i++){ dp[i][j] = max(dp[i][j+1],MAX)+Tree[i][j]; } } /*for(int j=h;j>=0;j--){ for(int i=1;i<=n;i++){ printf("dp[%d][%d]:%d\n",i,j,dp[i][j]); } }*/ int Max = 0; for(int i=1;i<=n;i++) Max = max(Max,dp[i][0]); printf("%d\n",Max); return 0; }