ZCMU—K

K - Last Hit
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Description

Kirito likes playing LOL, but he is a noob who never wins. His teammates don't want to play with him anymore. After practicing with AI for months, he thinks it's time to return to the battlefield!

Now there are N enemy minions in front of him. He wants to give them the last hit to get more gold. The last hit means that the minion's HP is reduced to or below zero (HP ≤ 0) after this hit. The minions are attacking a defense tower now. The tower has enough HP so it will not be destroyed and Kirito will not be attacked.

Kirito can reduce a minion's HP by Y at each hit while the tower's attack value is X. The tower has the same attack speed as Kirito's, so if Kirito choose to attack at every opportunity they will take turns hitting the minions. Kirito can choose not to attack but the tower will keep attacking until all minions are killed. Besides, Kirito can choose which minion to hit but the tower will always attack the minion according to the input sequence.

As an observer of the game, you want to know how many last hits can Kirito get at most. Suppose the tower attacks first.

Input

The first line of input contains an integer T, indicating the number of test cases (T ≤ 100).

The first line of each test case contains three integers N, X, Y (1 ≤ N ≤ 1000, 0 ≤ X, Y ≤ 109).

Next line contains N integers representing the HP of each minion (1 ≤ HP ≤ 109).

Output

One line for each test case, containing the number of last hits can Kirito get.

Sample Input

2 
3 1 1 
1 2 3 
3 2 1 
3 2 1

Sample Output

2
2

【分析】

题意:给你n个小兵,人的攻击力是Y,塔的攻击力是X,塔和人交替攻击,塔先攻并且每次必须攻击,人可以选择当前次攻击或不攻击,并且人可以随意选择目标攻击,塔只能按输入顺序从左往右攻击。问你最多能补到多少刀。

错了17次的题目...心态爆炸...先说一句数据...数据里居然有X=Y=0这种见鬼的数据...因为我先判断的X=0输出N。。所以错了17次...

首先要发现一点,人可以随意选择目标攻击,所以其实可以理解成人可以把当前的刀数存下来,等到之后需要时直接一次性打很多刀,这点挺容易发现的,发现了之后这道题就是个DP了

f[i][j]表示前i个小兵杀j个能剩下最多的刀数

f[i][j]的状态可以从两个方向来,

一个是f[i-1][j]也就是第i个人没杀,没杀的话就剩余刀数加上塔的攻击次数

一个是f[i-1][j-1]也就是第i个人杀了,需要杀的话就要看需要多少刀,也就是先让塔尽可能打,在塔的最后一刀之前自己补刀,

如果自己的剩余刀数加上当前塔的攻击次数足够的话就可以更新当前状态

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
long long f[1105][1105];
long long a[11005]; 
int main ()
{
    int pp;scanf("%d",&pp);
    while(pp--)
	{
        int n,X,Y;
        scanf("%d%d%d",&n,&X,&Y);
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
        if (Y==0)
		{
			printf("0\n");
			continue;
		}
		if (X==0)
        {
        	printf("%d\n",n);
        	continue;
		}
		
       	memset(f,-1,sizeof(f));
        f[0][0]=0;
        int ans=0;
        for(int i=1;i<=n;i++)
        {
			if (f[i-1][0]>=0)
            	if (a[i]%X==0) f[i][0]=max(f[i][0],f[i-1][0]+a[i]/X);
            	else f[i][0]=max(f[i][0],f[i-1][0]+a[i]/X+1);
            for(int j=1;j<=i;j++)
			{
                if(f[i-1][j]>=0)
                {
					if (a[i]%X==0) f[i][j]=max(f[i][j],f[i-1][j]+a[i]/X);
					else f[i][j]=max(f[i][j],f[i-1][j]+a[i]/X+1);
      			}
				if(f[i-1][j-1]>=0)
				{
					int ki=a[i]/X;if (a[i]%X==0) ki--;
					int last=a[i]-X*ki;
                    if( (f[i-1][j-1]+ki)>=(last/Y))
                    {
                      	int tt=(last/Y)+(last%Y==0?0:1);
					    f[i][j]=max(f[i][j],f[i-1][j-1]+ki-tt);
                	}
				}
                if (f[i][j]>=0) ans=max(ans,j);
            }
        }
		printf("%d\n",ans);
   }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值