山东省第六届省赛K题

题意描述:

题目原型来自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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值