LightOJ - 1017 Brush (III)

来源:互联网 发布:微群控营销软件 编辑:程序博客网 时间:2024/05/22 08:27

题目大意:有N个污点,每个污点有相应的坐标。现在有一个宽度为w的刷子,刷子可以使用k次,刷的时候,可以横刷到无穷
问最多可以刷掉多少个污点

解题思路:先离散化,预处理出每个y坐标的点,并统计一下该同一y坐标下,有多少个点
再处理一下,如果刷子的最下面刚好是该y坐标时,能刷到的所有污点数
接着就是DP了,用dp[i][j]表示刷子使用了i次,第i次刷的时候,刷子的最底部刷的是第j个y坐标的最大污点数
则dp[i][j] = dp[i - 1][k] + num[j], 其中y[k] + w < y[j],num[j]表示刷子的最下面刷的是y[j]时,能刷到的污点数

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 110;struct Point{    int x, y;}P[N];int n, w, k, cnt, cas = 1;int num[N], y[N], dp[N][N];int cmp(const Point &a, const Point &b) {    return a.y < b.y;}void init() {    scanf("%d%d%d", &n, &w, &k);    for (int i = 1; i <= n; i++)        scanf("%d%d", &P[i].x, &P[i].y);    sort(P + 1, P + 1 + n, cmp);    cnt = 1;    y[1] = P[1].y;    num[1] = 1;    for (int i = 2; i <= n; i++) {        if (P[i].y == P[i - 1].y) num[cnt]++;        else  {            y[++cnt] = P[i].y;            num[cnt] = 1;        }    }    for (int i = 1; i <= cnt; i++)         for (int j = i + 1; j <= cnt; j++)             if (y[i] + w >= y[j]) num[i] += num[j];}void solve() {    int ans = 0;    memset(dp, 0, sizeof(dp));    for (int i = 1; i <= cnt; i++) {        dp[1][i] = num[i];        ans = max(ans, dp[1][i]);    }    for (int i = 2; i <= k; i++)        for (int j = 1; j <= cnt; j++)             for (int l = 1; l < j; l++) {                if (y[l] + w >= y[j]) break;                if (y[l] + w < y[j] && dp[i][j] < dp[i - 1][l] + num[j])  {                    dp[i][j] = dp[i - 1][l] + num[j];                    ans = max(ans, dp[i][j]);                }            }    printf("Case %d: %d\n", cas++, ans);}int main() {    int test;    scanf("%d", &test);    while (test--) {        init();        solve();    }    return 0;}
0 0
原创粉丝点击