假设我们已经确定了要杀那几只怪,假设第i只怪在第j天被杀死,那么它对猎人造成的伤害就是 (a[i]+j∗d)(b[i]+j∗d)=a[i]∗b[i]+j2d2+j∗d∗(a[i]+b[i]) ( a [ i ] + j ∗ d ) ( b [ i ] + j ∗ d ) = a [ i ] ∗ b [ i ] + j 2 d 2 + j ∗ d ∗ ( a [ i ] + b [ i ] ) ,贪心的思想,我们一定是按照 a[i]+b[i] a [ i ] + b [ i ] 由小到大的顺序去杀这些怪。那么,我们先把所有怪按照 a[i]+b[i] a [ i ] + b [ i ] 排序,最终的答案序列一定是这个序列的子序列,接下来用DP。
f[i][j] f [ i ] [ j ] 表示前i只怪,总共杀了j只的最少消耗的血量,转移: f[i][j]=min(f[i−1][j],f[i−1][j−1]+(a[i]+j∗d)∗(b[i]+j∗d)) f [ i ] [ j ] = m i n ( f [ i − 1 ] [ j ] , f [ i − 1 ] [ j − 1 ] + ( a [ i ] + j ∗ d ) ∗ ( b [ i ] + j ∗ d ) )
时间复杂度: O(n2) O ( n 2 )
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 3006
#define LL long long
using namespace std;
int n,m,d;
LL ans[maxn],f[maxn][maxn],g[maxn][maxn];
struct data{
int x,y;
bool operator <(const data&b)const{return x+y>b.x+b.y;}
}a[maxn];
int main(){
freopen("hunter.in","r",stdin);
freopen("hunter.out","w",stdout);
scanf("%d%d%d",&n,&m,&d);
for(int i=1;i<=n;i++)scanf("%d",&a[i].x);
for(int i=1;i<=n;i++)scanf("%d",&a[i].y);
sort(a+1,a+1+n);
memset(g,127,sizeof(g));memset(ans,127,sizeof(ans));
for(int i=0;i<=n;i++)g[i][0]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++){
f[i][j]=g[i-1][j-1]+(LL)(a[i].x+d*(j-1))*(a[i].y+d*(j-1));
g[i][j]=min(f[i][j],g[i-1][j]);
ans[j]=min(ans[j],f[i][j]);
}
for(int i=1;i<=m;i++){
LL h;scanf("%lld",&h);
printf("%d\n",lower_bound(ans+1,ans+1+n,h)-ans-1);
}
return 0;
}