题解:P15436 [蓝桥杯 2025 国 Python B] 魔法护盾
zhunxin666 · · 题解
题目描述很清楚,我就不赘述了。
考虑动态规划。
状态就设的直白一点,设
初始化就是
那转移方程就很好写了,分为两种:
- 不使用护盾增幅,那我们的
dp_j 就可以直接从dp_j+s_i 转移过来。 - 使用护盾增幅,那
dp_j 就需要从dp_{j-1}+2 \times s_i 转移过来。
注意过程对
但是,我们考虑到,目前在第
Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,c,b,s[N],a[N],dp[N],ans;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>c>>b;
for(int i=1;i<=n;i++) cin>>s[i];
for(int i=1;i<=n;i++) cin>>a[i];
dp[0]=b;
for(int i=1;i<=n;i++){
int sum=9e18;
for(int j=i;j>=0;j--){
dp[j]=min(dp[j]+s[i],c);
if(j!=0) dp[j]=max(min(dp[j-1]+2*s[i],c),dp[j]);
if(dp[j]>=a[i]) sum=min(sum,j);
else dp[j]=-1e9;
}
ans=max(ans,sum);
if(ans==9e18){
cout<<-1;
return 0;
}
}
cout<<ans;
return 0;
}
:::info[一种错误的做法。] 这道题我一开始拿贪心做的,代码如下:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=10100;
int n,c,b,s[N],a[N],ans;
priority_queue <int> pq;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>c>>b;
for(int i=1;i<=n;i++) cin>>s[i];
for(int i=1;i<=n;i++) cin>>a[i];
int sum=b,vis=1;
for(int i=1;i<=n;i++){
if(s[i]>0) pq.push(s[i]);
sum+=s[i],sum=min(sum,c);
while(sum<a[i]&&!pq.empty()){
int t=pq.top();
pq.pop();
sum+=t,sum=min(sum,c);
ans++;
}
if(sum<a[i]){
vis=0;
break;
}
}
if(!vis) cout<<-1;
else cout<<ans;
return 0;
}
但其实这是错误的。
这个贪心相当于是一个反悔贪心,跳到之前的关卡使用护盾增幅。
问题很明显,我们不知道当时的关卡使用护盾增幅之后的护盾有没有超过
感谢观看!