这里写自定义目录标题
问题描述
JiaoShou在爱琳大陆的旅行完毕,即将回家,为了纪念这次旅行,他决定带回一些礼物给好朋友。
在走出了怪物森林以后,JiaoShou看到了排成一排的N个石子。
这些石子很漂亮,JiaoShou决定以此为礼物。
但是这N个石子被施加了一种特殊的魔法。
如果要取走石子,必须按照以下的规则去取。
每次必须取连续的2*K个石子,并且满足前K个石子的重量和小于等于S,后K个石子的重量和小于等于S。
由于时间紧迫,Jiaoshou只能取一次。
现在JiaoShou找到了聪明的你,问他最多可以带走多少个石子。
输入格式
第一行两个整数N、S。
第二行N个整数,用空格隔开,表示每个石子的重量。
输出格式
第一行输出一个数表示JiaoShou最多能取走多少个石子。
样列输入
8 3
1 1 1 1 1 1 1 1
样列输出
6
思路
最开始思路就是直接遍历,但仅成功第二个数据,第一个数据不知道到为什么没有成功,后几个超时
#include <bits/stdc++.h>
using namespace std;
int get(vector<int> nums)
{
return 0;
}
int main()
{
ios::sync_with_stdio(false);
long long n, m;
cin >> n >> m;
long long x1 = 0;
long long x2 = 0;
long long s=0;
int flag = 0;
vector<int> a(n+1);
for(long long i=0;i<n;i++)
{
cin >> a[i];
}
for (long long i = n/2; i >=1; i --)
{
for (long long j = 0; j <= n / 2 - i; j++)
{
x1 = accumulate(a.begin() + j, a.begin() + i + j, 0LL);
if (x1 > m)
{
continue;
}
x2 = accumulate(a.begin() + i + j, a.begin() + i + i + j, 0LL);
if (x2 > m)
{
continue;
}
else
{
cout << i * 2;
flag = 1;
break;
}
}
if (flag == 1)
{
break;
}
}
return 0;
}
超时改用二分方法
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int M = 1e6+5;
int N;long long S;
long long val[M], a[M]; //前缀和,石子每个的质量
bool check(int mid)
{
for (int i = mid; i <= N-mid; i++)
{
if (val[i] - val[i - mid] <= S && val[i + mid] - val[i] <= S)
{
return true; //存在符合情况的
}
}
return false;
}
int main()
{
cin >> N >> S;
for (int i = 1; i <= N; i++)
{
cin >> a[i];
val[i] = val[i - 1] + a[i]; //求前缀和
}
//找符合要求的最大值采用二分法
int l = 1, r = N;
while (l < r)
{
int mid = l + r + 1 >> 1; //(l+r)/2,这里mid代表了单个区域所取石子的股数
if (check(mid))//成功说明当前区域可取
{
l = mid;//增大l-》增大下一次的mid
}
else
r = mid - 1;//r减小-》减小下一次的mid
}
cout << 2 * l << endl;
}