题意:有一把刷子宽度为w,只能沿x轴方向刷,现给出n个点,问这把刷子刷k次,最多能刷到几个点
题解:很简单的一道dp,因为刷子只能沿x轴刷,所以只要看纵坐标就好了,这样输入的时候就不用结构体,直接单把纵坐标存在一个数组里就可以了。先把纵坐标排序,然后用dis数组记录下刷子的一段从每个点开始最多能刷到多少个点,接下来问题就简单了
状态转移方程:dp[i][j] = max(dp[i - 1][j], dp[i - dis[i]][j - 1] + dis[i])
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#define M 110
using namespace std;
int a[M];
int dis[M];
int dp[M][M];
int main()
{
int T;
scanf("%d", &T);
for(int t = 1; t <= T; t++)
{
int n, w, k;
scanf("%d %d %d", &n, &w, &k);
int x;
for(int i = 0; i < n; i++)
scanf("%d %d", &x, &a[i]);
sort(a, a + n);
memset(dis, 0, sizeof(dis));
for(int i = 0; i < n; i++)
for(int j = 0; j <= i; j++)
if(a[i] - a[j] <= w)dis[i]++;
memset(dp, 0, sizeof(dp));
for(int i = 0; i < n; i++)
{
for(int j = 1; j <= k; j++)
{
if (i < dis[i])
dp[i][j] = dis[i];
else
dp[i][j] = max(dp[i - 1][j], dp[i - dis[i]][j - 1] + dis[i]);
}
}
printf("Case %d: %d\n", t, dp[n - 1][k]);
}
return 0;
}