题目链接

50分做法

挺显然的一个做法,因为金币量是单调的(如果你花i枚金币可以得到最优解,i+1枚也一定可以),所以可以二分答案

然后对于二分出来的每个答案,都做一遍dp,效率$O(n^2logn)$

#include <cstdio>
#include <cstring>
using namespace std;
#define N 500100
inline int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    return x*f;
}
int n,d,k,a[N],s[N],dp[N];
int max(int x,int y){return x>y?x:y;}
bool check(int g){
    memset(dp,128,sizeof(dp));
    int t1=(d-g)?d-g:1,t2=d+g,mx=0;
    dp[0]=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<i;j++){
            if(a[i]-a[j]>=t1&&a[i]-a[j]<=t2)
                dp[i]=max(dp[i],dp[j]+s[i]);
        }
    }
    for(int i=1;i<=n;i++)mx=max(dp[i],mx);
    if(mx>=k)return 1;
    return 0;
}
int main(){
    n=read();d=read();k=read();
    for(int i=1;i<=n;i++)
        a[i]=read(),s[i]=read();
    int ans=0,l=0,r=10000000;
    while(l<=r){
        int mid=(l+r)>>1;
        if(check(mid))r=mid-1,ans=mid;
        else l=mid+1;
    }
    if(ans)printf("%d\n",ans);
    else puts("-1");
    return 0;
}
50分做法

相关文章: