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; }