【DBSDFZOJ 4430】陶陶摘苹果(DP)

来源:互联网 发布:可以借钱的软件 编辑:程序博客网 时间:2024/05/18 00:03

Description

陶陶家的院子里有一棵苹果树,每到秋天树上就会结出 n 个苹果。苹果成熟的时候,陶
陶就会跑去摘苹果。
陶陶的手不能弯 (他仅能把手伸直),当且仅当陶陶达到的高度与苹果的高度相等的时
候,陶陶才能摘到苹果。
好在陶陶有 m 个板凳,每个板凳的高度可以在区间 [li, ri] 之间上下移动 (即可以随时 变为该区间中任何一个值)。当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试。
但是搬板凳对陶陶来说是一件费力的事情,所以他只能选择 k 个板凳来使用。
现在已知 n 个苹果到地面的高度,m 个板凳的高度区间,陶陶能选择的板凳数 k,以
及陶陶把手伸直能达到的高度 h,请帮陶陶算一下她最多能够摘到的苹果的数目。假设她碰
到苹果,苹果就会掉下来。

Input

第一行四个正整数 n,m,h,k,表示苹果的数量、板凳的数量、陶陶把手伸直能达到
的高度和陶陶最多选择的板凳数量。
第一行包含 n 个正整数,第 i 个正整数 ai 表示第 i 个苹果到地面的高度,两个相邻的
整数之间用一个空格隔开。
接下来 m 行,每行两个非负整数 li,ri,表示第 i 个板凳的高度区间。

Output

一个数,表示最多摘到的苹果数。

Sample Input

10 5 110 3
100 200 150 140 129 134 167 198 200 111
0 30
20 40
90 100
100 110
50 60

Sample Output

7

Data Constraint

对于 30% 的数据,m≤10,ai, h≤1000,li

解题思路

dp,先将板凳按右端点排序,用f[i][j]表示一共选了i个板凳,最后一个板凳编号为j。所以可以枚举上一个板凳的位置,转移方程为f[i][j]=max{ f[i-1][i-1]~f[i-1][j-1] }。

代码

#include <bits/stdc++.h>using namespace std;int n,m,h,k;int tree[1000005];int f[205][205];struct qj{    int l,r;}d[205];bool cmp(qj a,qj b){return a.r<b.r;}int main(){    scanf("%d%d%d%d",&n,&m,&h,&k);    int Max=-1;    for(int i=1;i<=n;++i){        int a;        scanf("%d",&a);a-=h;        if(a<0) continue;        Max=max(Max,a);        tree[a]+=1;    }    for(int j=1;j<=m;++j){        scanf("%d%d",&d[j].l,&d[j].r);        Max=max(Max,d[j].r);    }    for(int i=1;i<=Max;++i)     tree[i]+=tree[i-1];    sort(d+1,d+m+1,cmp);    int ans=0;    for(int i=1;i<=k;++i)        for(int j=1;j<=m;++j)            for(int p=i-1;p<j;++p){                f[i][j]=max(f[i][j],f[i-1][p]+tree[d[j].r]-max((d[j].l?tree[d[j].l-1]:0),tree[d[p].r]));                ans=max(ans,f[i][j]);            }    printf("%d",ans);    return 0;}