题目大概说一个平面上分布n个灰尘,现在要用一个宽w的刷子清理灰尘:选择一个起点,往水平线上扫过去这个水平线上的灰尘就消失了。问最多进行k次这样的操作能清理最多多少灰尘。
没什么的DP。
- 先按垂直坐标给灰尘们排个序,
- 然后d[i][k]表示前i个灰尘中,进行到第k次清理操作时刷子底部在第i个灰尘的竖坐标能清理的最多灰尘,
- 最后转移一个一个往前枚举就OK了,规模很小。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int d[111][111]; 6 int main(){ 7 int t,n,w,K,x[111],y; 8 scanf("%d",&t); 9 for(int cse=1; cse<=t; ++cse){ 10 scanf("%d%d%d",&n,&w,&K); 11 for(int i=0; i<n; ++i){ 12 scanf("%d%d",&y,x+i); 13 } 14 sort(x,x+n); 15 memset(d,0,sizeof(d)); 16 d[0][1]=1; 17 int res=1; 18 for(int i=1; i<n; ++i){ 19 int cnt=1; 20 for(int k=0; k<i; ++k){ 21 if(x[i]-x[k]<=w){ 22 ++cnt; 23 } 24 } 25 d[i][1]=cnt; 26 res=max(res,d[i][1]); 27 for(int j=2; j<=K; ++j){ 28 int mx=0; 29 for(int k=0; k<i; ++k){ 30 if(x[i]-x[k]<=w){ 31 break; 32 } 33 mx=max(mx,d[k][j-1]); 34 } 35 if(mx!=0){ 36 d[i][j]=mx+d[i][1]; 37 res=max(res,d[i][j]); 38 } 39 } 40 } 41 printf("Case %d: %d ",cse,res); 42 } 43 return 0; 44 }