2021.2.17动态规划基础测试T3

该博客讨论了一个模拟DOTA游戏中补兵情况的问题,通过动态规划算法解决。玩家与老鹿轮流攻击小兵,计算最多能补刀的小兵数。题目描述了输入输出格式、数据范围和样例,并设置了资源与时间限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

T3补兵

题目描述
对于一个DOTA玩家,补兵个数(Creep Score)是衡量一名选手能力的重要指标,特别是打路人局的时候,补兵能力就更加关键了,因为常常会有队友和你抢补刀,比如,队友操控的老鹿在开大收兵,如果你操控的是幽鬼,就需要在老鹿的AOE中偷偷补上几刀来保证自己的发育。

我们自己建立一个模型来大致模拟以下情况:

现在有n个小兵,每个小兵有自己的血量Ai(血量一定是正整数),你和老鹿轮流对小兵进行攻击。每次,你可以选择对某个小兵造成1点伤害(或者你可以选择不作为),接着,老鹿会对所有小兵造成1点AOE伤害,如此往复,直到所有小兵都死亡(血量变成0)。如果你对某个小兵造成致命伤害(使他的血量从1变成0).那么你就补刀成功了!

对于给定的情形,你需要计算你最多可以补刀多少的小兵。
输入格式
本题有多组测试数据,第一行为一个整数T,表示测试组数。 对于每一组数据,第一行一个整数N,表示小兵的个数,随后第二行N个正整数,表示每个小兵的血量。
输出格式
对于每一组数据,输出一个整数M,表示补兵的最大数量。
输出格式
对于30%的数据,N ≤\leq 100,对于50%的数据,N ≤\leq 500,T ≤\leq 30, a[i]a[i]a[i] ≤\leq 500,对于1000%的数据,1 ≤\leq N ≤\leq 500,1 ≤\leq T ≤\leq 70,1 ≤\leq a[i]a[i]a[i] ≤\leq 1000。
样例

样例输入

1
5
5 5 5 5 5

样例输出

2

资源与时间限制

内存:256MB
时间:1s

正解思路

在这里插入图片描述
正解代码

#include<bits/stdc++.h>
using namespace std;
const int N=1086;
int cnt[N],c[N],f[N][N],a[N],sta[N];
int main()
{
	freopen("cs.in","r",stdin);
	freopen("cs.out","w",stdout);
	int t;
	cin>>t;
	while(t--)
	{
		int n,maxx=0;
		cin>>n;
		memset(cnt,0,sizeof(cnt));
		memset(c,0,sizeof(c));
		memset(f,0,sizeof(f));
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			++cnt[a[i]];
			maxx=max(maxx,a[i]);//找到补兵攻击的最大次数 
		}
		int top=0;
		for(int i=1;i<=maxx;i++)
		{
			if(cnt[i]==0) sta[++top]=i;
			else{
				while(cnt[i]>1&&top>0)
				{
					c[sta[top--]]=i;
					--cnt[i];
				}
				c[i]=i;
			}
		} 
		int ans=0;
		for(int i=1;i<=maxx;++i)
		{
			for(int j=0;j<=i;++j)
			{
				if(j>0) f[i][j]=f[i-1][j-1];
				if(c[i]!=0&&j+c[i]-i<i)
				{
					f[i][j]=max(f[i][j],f[i-1][j+c[i]-i]+1);
				}
				ans=max(ans,f[i][j]);
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值