1. 程式人生 > >[luogu 1107] [BJWC2008]雷濤的小貓 {DP}

[luogu 1107] [BJWC2008]雷濤的小貓 {DP}

題目

https://www.luogu.org/problemnew/show/P1107


解題思路

f [ i ] [ j ]

f[i][j] 表示 i i 高度在第 j j 棵樹的最優值,
a
[ j ] [ i ] a[j][i]
表示第 j
j
棵樹 i i 高度的個數。
f [ i ] [ j ] = f [ i + 1 ] [ j ] + a [ j ] [ i ] f[i][j]=f[i+1][j]+a[j][i] 即直接往下跳
f [ i ] ] [ j ] = m a x ( f [ i + d e l a ] [ j ] + a [ j ] [ i ] ) f[i]][j]=max(f[i+dela][j]+a[j][i]) 即從另一棵樹跳到這裡
明顯 m a x ( f [ i + d e l a ] [ j ] ) max(f[i+dela][j]) 是知道的,所以我們可以用 g [ i ] g[i] 來處理第 i i 高度的最大值。


程式碼

#include<cstdio>
#include<string>
#define rr register
using namespace std; 
int f[2101][2101],n,m,h,g[2101],a[2101][2101]; 
inline int maxx(int x,int y){if (x>y) return x; return y;}
inline int read()
{
	int p=0;  char c=getchar(); 
	while (!isdigit(c)) c=getchar(); 
	while (isdigit(c)) p=(p<<3)+(p<<1)+c-48,c=getchar(); 
	return p; 
}
int main()
{
	n=read(),h=read(),m=read();
	for (rr int i=1;i<=n;++i)
	 {
	 	int w=read(),t; 
	 	for (rr int j=1;j<=w;++j) a[i][t=read()]++; 
	 }
	for (rr int i=h;i;--i)
	{
		for (rr int j=1;j<=n;++j) f[i][j]=f[i+1][j]+a[j][i]; 
		if (i<=h-m) 
			for (rr int j=1;j<=n;++j)  
			f[i][j]=maxx(f[i][j],g[i+m]+a[j][i]); 	
		for (rr int j=1;j<=n;++j) g[i]=maxx(f[i][j],g[i]); 
	}
	printf("%d",g[1]); 
}