1. 题目
2. 分析
题意是有一条项链,项链上每颗珠子的价值各不相同,火星上的人习惯用珠子付款,付款的珠子必须是连续的,可以是一颗也可以是多颗,现在首行给出两个数,第一个数是珠子的数量,第二个是要付款的价格,然后下一行给出每个珠子的价值,现要求你输出能付款的方式,给出珠子的位置,若不能恰好付款,则输出损失最少的方式。
3. 解题过程
- 实际上这是一道连续子序列的问题,如果硬刚会有两个测试点过不了,超时,所以需要用二分法这一算法解决。
- 总体思路是建立一个sum[i]数组,i代表1~i之间的价值总和,然后用二分法,利用一头一尾差值去求m,求出最接近m的位置。
- 最后根据求出的m是不是最接近m,去记录一头一尾。
- 请看代码:
#include<iostream>
#include<vector>
using namespace std;
vector<int> sum, resultArr;
int n, m;
void Func(int i, int &j, int &tempsum)
{
int left = i, right = n;
while(left < right)
{
int mid = (left + right) / 2;
if(sum[mid] - sum[i-1] >= m)
{
right = mid;
}
else left = mid + 1;
}
j = right;
tempsum = sum[j] - sum[i-1];
}
int main()
{
scanf("%d%d", &n, &m);
sum.resize(n+1);
for(int i = 1; i <= n; i++)
{
scanf("%d", &sum[i]);
sum[i] += sum[i-1];
}
int minans = sum[n];
for(int i = 1; i <= n; i++)
{
int j, tempsum;
Func(i, j, tempsum);
if(tempsum > minans) continue; // 求出最小tempsum,大于就可以忽略了
if(tempsum >= m)
{
if(tempsum < minans) // 一旦找到更小的就初始化
{
resultArr.clear();
minans = tempsum;
}
resultArr.push_back(i);
resultArr.push_back(j);
}
}
for(int i = 0; i < resultArr.size(); i+=2)
{
printf("%d-%d\n", resultArr[i], resultArr[i+1]);
}
return 0;
}
4. 小结
-
二分法是对付查找多数据的利器
感谢阅读