lightoj 1017 - Brush (III) (DP)

Samir returned home from the contest and got angry afterseeing his room dusty. Who likes to see a dusty room after a brain stormingprogramming contest? After checking a bit he found a brush in his room whichhas width w. Dusts are defined as 2D points. And since they arescattered everywhere, Samir is a bit confused what to do. He asked Samee and foundhis idea. So, he attached a rope with the brush such that it can be movedhorizontally (in X axis) with the help of the rope but in straight line.He places it anywhere and moves it. For example, the y co-ordinate ofthe bottom part of the brush is 2 and its width is 3, so the ycoordinate of the upper side of the brush will be 5. And if the brush is moved,all dusts whose y co-ordinates are between 2 and 5 (inclusive) will becleaned. After cleaning all the dusts in that part, Samir places the brush inanother place and uses the same procedure. He defined a move as placingthe brush in a place and cleaning all the dusts in the horizontal zone of thebrush.

You can assume that the rope is sufficiently large. SinceSamir is too lazy, he doesn't want to clean all the room. Instead of doing ithe thought that he would use at most k moves. Now he wants to find themaximum number of dust units he can clean using at most k moves. Pleasehelp him.

Input

Input starts with an integer T (≤ 100),denoting the number of test cases.

Each case starts with a blank line. The next line containsthree integers N (1 ≤ N ≤ 100), w (1 ≤ w ≤ 10000)and k (1 ≤ k ≤ 100). N means that there are N dustpoints. Each of the next N lines contains two integers: xiyi denoting the coordinates of the dusts. You can assume that (-109≤ xi, yi ≤ 109) and all pointsare distinct.

Output

For each case print the case number and the maximum numberof dusts Samir can clean using at most k moves.


先预处理对于每一个y值,有多少可以清理掉的点

定义dp[i][j] := 前i个y值移动j步可以清理的最大垃圾量. 如果没有一次可以清理w行这个条件的话,类似01背包 dp[i][j] = max(dp[i-1[j], dp[i-1]j-1] + v);   v(v是第i个y值对应的垃圾个数)

添上这个条件后,我们需要看上一次清理垃圾清理到了第几行.

假如说对y进化降序数据是

i       x      y

1     0      4

2     0      3

3     0      2

4     0      1

此时w = 2

当i = 4 时

dp[4][j] = max(dp[3][j], dp[1][j-1] + sigam(v));

当选择清理第4行垃圾时,他最多也可以清理掉i = 3,i = 2 行的垃圾。因为他们对应的 y2 - w <= y4.

于是他应该由y = 1 转移过来。

/***********************************************
 * Author: fisty
 * Created Time: 2015/6/25 22:42:29
 * File Name   : 1017.cpp
 *********************************************** */
#include <iostream>
#include <cstring>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <algorithm>
using namespace std;
#define Debug(x) cout << #x << " " << x <<endl
#define Memset(x, a) memset(x, a, sizeof(x))
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef pair<int, int> P;
#define FOR(i, a, b) for(int i = a;i < b; i++)
#define MAX_N 110
int t;
int n, w, k;
struct node{
    int y;
    int num;
}p[MAX_N];
int dp[MAX_N][MAX_N];
bool cmp(node a, node b){
    return a.y > b.y;
}
int main() {
    //freopen("in.cpp", "r", stdin);
    cin.tie(0);
    ios::sync_with_stdio(false);
    cin >> t;
    int cnt = 1;
    while(t--){
        Memset(p, 0);
        map<int, int> mp;
        cin >> n >> w >> k;
        FOR(i, 0, n){
            int x, y;
            cin >> x >> y;
            if(mp.find(y) == mp.end()){
                mp[y] = 1;
            }else{
                mp[y]++;
            }
        }
        map<int, int>::iterator it;
        int m = 0;
        for(it = mp.begin(); it != mp.end(); it++){
            p[++m].y = it->first;
            p[m].num = it->second;
        }
        sort(p+1, p+1+m, cmp);
      
        Memset(dp, 0);
        for(int i = 1;i <= m; i++){
            for(int j = 1;j <= k; j++){
                int sum = 0;
                for(int l = i;l >= 1; l--){
                    if(p[l].y - p[i].y > w) break;    
                    sum += p[l].num;
                    dp[i][j] = max(dp[i-1][j], dp[l-1][j-1]+sum);        
                }
            }
        }
        cout << "Case" << " " << cnt++ << ": "; 
        cout << dp[m][k] << endl;
    }
    return 0;
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值