题意描述:
题目原型来自LOL游戏,一个人和一座塔,共同打n个怪,每个怪都有一定的血量,塔和人都有无限血。每一轮攻击都是塔先打,而且塔只按顺序打怪物,人后打,但人可以选择任意一个攻击,但是人在每一轮可以攻击也可以不攻击。求人最多可以给几个怪物以最后一击。
1<=n<=1000, 塔,人的每次攻击力x、y 在 0 - 1e9之间 ,怪的血量在 ai在 1 - 1e9之间。
解法描述:
定义 : 由于每一轮人可以攻击可以不攻击,那么人可以保留这次攻击,记为一次可用攻击数。
定义 : d(i,j)为前i个怪 人杀死j个 所能剩余的最大可用攻击数。
定义:b(i) 为 为怪i 再被 塔打一下就死时的血量 , c(i) 为人把i滴血打完所需次数。
状态转移: 当 i-1 > = j 时 d(i,j)->d(i-1,j); 当且仅当 (d(i-1,j-1)+ (ai - b(i))%x ) >= c(b(i)) 时 d(i,j)->d(i-1,j-1);
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
typedef long long LL;
const int inf = 1e9;
const int N = 1010;
LL d[N][N],x,y,a[N],n;
bool vis[N][N];
LL dp(int i,int j){
if(vis[i][j]) return d[i][j];
vis[i][j]=1;
if(i==0) return d[i][j]=0;
d[i][j] = -inf;
if(i-1 >= j) d[i][j]=dp(i-1,j)+(a[i]/x +(a[i]%x==0 ? 0:1));
if(j>0){
LL pre = dp(i-1,j-1);
int lef=(a[i]%x==0 ? x:a[i]%x),add=a[i]/x-(a[i]%x==0 ? 1:0);
LL need = lef/y+(lef%y==0 ? 0:1);
pre+=add;
if(pre >= need) d[i][j]=max(d[i][j],pre-need);
}
return d[i][j];
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%lld %lld %lld",&n,&x,&y);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
memset(vis,0,sizeof(vis));
if(y==0 || x==0) {
if(y == 0) printf("0\n");
else if(x == 0) printf("%d\n",n);
continue;
}
for(int i=n;i>=0;i--){
if(dp(n,i)>=0) {
printf("%d\n",i);
break;
}
}
}
return 0;
}