C:小红打怪
题目要求击杀所有怪兽的最少回合,如果 x 个回合可以击杀完,那么 (x+1) 回合肯定也可以击杀完,答案满足单调性,所以考虑二分。
至于该怎么判断是否 x 回合可以击杀完所有怪兽,就是遍历怪兽,处理血量大于 limit 的怪兽,因为小于等于 limit 的可以通过小红的集体伤害减为 0,所以我们只考虑大于 limit 的怪兽;如果第 i 只怪兽以及第 i+1 只怪兽血量都大于limit,那么我们使用队友 2 的技能,用一个技能攻击两只怪兽;否则就用队友 1 的技能,对单只怪兽造成伤害。
(不能对原数组排序哦,排序会影响怪兽的相邻关系)
具体细节请看代码,写了非常详细的注释
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t,n,m;
bool check(vector<int>a, int limit)//check函数里的数组a不能对外面的数组造成变化,否则会影响以后的check
{
int cnt1=limit;//队友1的技能还能使用的次数
int cnt2=limit;//队友2的技能还能使用的次数
for(int i=0;i<n;i++)
{
if(a[i]>limit)
{
if(a[i+1]>limit && cnt2>0)//如果下一只怪兽血量也是 > limit,以及队友 2 的技能次数>0,还能用
{
int temp=min(a[i],a[i+1])-limit;
if(cnt2>=temp)//如果队友2技能次数可以使得怪兽i的血量减到limit
{
cnt2-=temp;
a[i]-=temp,a[i+1]-=temp;
}
else//如果不够,那就全部用掉
{
a[i]-=cnt2,a[i+1]-=cnt2;
cnt2=0;//队友2技能不能再用了
}
}
if(a[i]>limit)//单只怪兽血量 > limit 或者 上面的if还没有完全处理完a[i],就是还没有将a[i]降到limit
{
int temp=a[i]-limit;//需要使用这么多次队友1的技能
if(cnt1>=temp)
{
cnt1-=temp;
a[i]-=temp;
}
else
{
a[i]-=cnt1;
cnt1=0;
if(cnt2>=a[i]-limit)//队友1技能使用次数不够了,用队友2的技能
{
int temp2=a[i]-limit;
a[i]-=temp2;
cnt2-=temp2;
//a[i] -= a[i]-limit;
//cnt2 -= a[i]-limit;//写成这样不对哦,因为a[i]会被改变
}
else
return false;//如果队友2的技能也不能用了,那就说明用 limit 回合是不能击杀所有怪兽的,返回false
}
}
}
}
return true;
}
void solve(){
cin>>n;
vector<int> v(n+5);
int mx=0;
for(int i=0;i<n;i++){
cin>>v[i];
mx=max(mx,v[i]);
};
int l=0,r=mx;
int ans=0;
while(l<=r)
{
int mid=(r-l)/2+l;
if(check(v, mid))
{
ans=mid;
r=mid-1;
}
else
l=mid+1;
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
t=1;
//cin>>t;
while(t--){
solve();
}
return 0;
}
如果题解对你有所帮助,还请给我点个赞,谢谢!