题意:给N个点,然后刷子的宽度w,刷子可以平行于x轴无限刷,给出可以刷的次数,求刷子可以覆盖多少个点。
因为可以平行于x轴无限刷,所以不需要考虑x轴上的点, 直接对Y轴进行排序,预处理一个数组mv,mv[i]表示如果刷子的底部刷到了i,那么会向上影响mv[i]个点。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#pragma warning (disable :4996)
using namespace std;
const int Max = 105;
int dp[Max][Max], mv[Max], a[Max];
bool cmp(int a, int b)
{
return a >= b;
}
int main()
{
int T, w, n, k, x;
scanf("%d", &T);
for (int t = 1; t <= T; t++)
{
scanf("%d %d %d", &n, &w, &k);
for (int i = 0; i < n; i++)
scanf("%d %d", &x, &a[i]);
sort(a, a + n, cmp);
memset(mv, 0, sizeof(mv));
memset(dp, 0, sizeof(dp));
for (int i = 0; i < n; i++)//预处理mv
{
int pre = i;
int now = i;
while (a[pre] - a[now] <= w&&pre >= 0)
pre--;
mv[i] = now - pre;
}
for (int i = 0; i < n; i++)
{
for (int j = 1; j <= k; j++)
{
if (i >= mv[i])
dp[i][j] = max(dp[i - 1][j], dp[i - mv[i]][j - 1] + mv[i]);//前面表示不刷i点,后面表示刷i点,以及把此点向上所影响的所有点都刷掉
else
dp[i][j] = mv[i];
}
}
printf("Case %d: %d\n", t, dp[n - 1][k]);
}
return 0;
}