在蒜厂年会上有一个抽奖,在一个环形的桌子上,有 nn 个纸团,每个纸团上写一个数字,表示你可以获得多少蒜币。但是这个游戏比较坑,里面竟然有负数,表示你要支付多少蒜币。因为这些数字都是可见的,所以大家都是不会出现的赔的情况。
游戏规则:每人只能抓一次,只能抓取一段连续的纸团,所有纸团上的数字和就是你可以获得的蒜币。
蒜头君作为蒜厂的一员在想,我怎么可以获得最多的蒜币呢?最多能获取多少蒜币呢?
因为年会是发奖,那么一定有大于 00 的纸团。
输入格式
第一行输入一个整数 nn,表示有 nn 个纸团。
第二行输入输入 nn 个整数 a_ia
i
,表示每个纸团上面写的数字(这些纸团的输入顺序就是环形桌上纸团的摆放顺序)。
输出格式
输出一个整数,表示蒜头君最多能获取多少蒜币。
样例输入 复制
3
1 -2 1
样例输出 复制
2
题解:做这题的时候首先看到题就把这个数组开2陪长度做,结果只过了60%,然后看了下别人的做法,这个题目答案有俩种可能,一种是直接在1到n中取到,另一种是在循环数组中取到,在循环数组中取到的话,我们可以把总和减去负最大连续和 ,把数组每个数乘以-1;然后求出最大连续和ans2,
然后答案为sum-(-ans);
ac代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
long long n,sum,sum1,ans1,ans2,ans;
int a[100005];
cin>>n;
sum=0;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
sum1=0;ans1=0;
for(int i=0;i<n;i++)
{
sum1+=a[i];
ans1=max(ans1,sum1);
if(sum1<0)
{
sum1=0;
}
}
for(int i=0;i<n;i++)
a[i]=-a[i];
sum1=0;ans2=0;
for(int i=0;i<n;i++)
{
sum1+=a[i];
ans2=max(ans2,sum1);
if(sum1<0)
{
sum1=0;
}
}
//最大连续和可能在1到n中取到,也可能在循环数组中取到。取俩者最大值。
ans=max(ans1,sum+ans2);//sum-(-ans2) 删掉负数连续和
cout<<ans<<endl;
return 0;
}
过60%代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
long long n,sum=0,count1=0,ans=0;
int a[100005];
cin>>n;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
if(a[i]>=0)
{
count1++;
}
}
if(count1==n)
{
for(int i=0;i<n;i++)
{
ans+=a[i];
}
}
else
{
ans=0;sum=0;
for(int i=0;i<2*n;i++)
{
int j=i%n;
sum+=a[j];
ans=max(ans,sum);
if(sum<0)
{
sum=0;
}
}
}
cout<<ans<<endl;
return 0;
}
本文探讨了一种基于环形数组的最大子数组和问题,即蒜厂年会抽奖游戏中如何选择连续纸团以获取最大蒜币收益。文章通过两种策略解决此问题:一是在原始数组中寻找最大连续和,二是通过求负最大连续和并从总和中减去它来考虑跨越两端的情况。
836

被折叠的 条评论
为什么被折叠?



