2.26 贪心+前缀和
题目分析
贝和埃分蛋糕,n个蛋糕,大小不一从a1到aN,两者轮流进行以下操作:
- 贝的操作: 她每次选择两个相邻的蛋糕,将它们堆叠成一个新的蛋糕,蛋糕的大小等于这两个蛋糕的和
- 埃的操作: 她每次选择最左边或最右边的一个蛋糕,将其藏起来
游戏结束时,剩下的唯一一个蛋糕由贝吃掉,而埃则吃掉她藏起来的所有蛋糕
贝和埃都会采用最优策略来尽量让自己得到更多的蛋糕。我们的目标是,给定 N 个蛋糕的大小,计算在两者最优策略下,贝和埃分别会吃到多少蛋糕
思路
贝为了防止他搓出的大蛋糕被埃抢,他的一切行为都是被动的,所以两人策略为:
-
贝:第一次必须拿中间两个蛋糕,之后必须根据埃的选择,向反方向合并蛋糕,才能保证不会被埃拿走
-
埃:从两边向中间拿蛋糕,使自己的蛋糕尽可能大
我们可以发现,埃可以找到一种最优方案,思路为:遍历埃的所有可能方案,找到最优方案,再求贝的
代码关键:
求埃拿走的蛋糕数(cnt)
因为贝先行动,举几个例子可以发现,在N为偶数时贝拿走的蛋糕比埃多2个,可列式:cnt + cnt + 2 = n,解得cnt = (n - 2) / 2
用前缀和,埃和贝的蛋糕总和都可用前缀和快速求出
代码实现
以下是用 C++ 实现的代码,它模拟了这个游戏的博弈过程,并计算出每个测试用例中贝和埃各自能吃到的蛋糕量。
#include<iostream>
#include<vector>
using namespace std;
using ll=long long;
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--){
ll n,cnt;cin>>n;
vector<ll> a(n+1),sum(n+1);
for(int i=1;i<=n;i++){
cin>>a[i];
sum[i]=sum[i-1]+a[i];//前缀和
}
cnt=(n-2)/2;//埃的蛋糕数
ll ai=0,be=0;//埃和贝得到的蛋糕
//埃有主动权,枚举埃的可能,取最优
ll i=1,j=n;//贝的范围,被动决定
for(int k=0;k<=cnt;k++){
ll al=sum[k]+(sum[n]-sum[n-cnt+k]);//埃的和
if(al>ai){
ai=al;//更新埃的和
i=k+1,j=n-cnt+k;//更新贝的范围
}
}
be=sum[j]-sum[i-1];//最后,根据范围计算贝的和
cout<<be<<' '<<ai<<'\n';
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!