山东省第六届省赛K题

来源:互联网 发布:鹿晗用的直播软件 编辑:程序博客网 时间:2024/04/27 13:22

题意描述:

题目原型来自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 0
原创粉丝点击