题目:
上班了,小程每天晚上都要坐公交车回家
公交车每天晚高峰都很拥挤,但是好在小程不用那么着急回家,可以在公司里坐一会。等高峰期一过,小程再回家。因为要时刻知道当前是否在高峰期,小程需要知道当前公交线路的拥挤段是哪里。
已知小程乘坐的公交车线路有n个站,从起点站到终点站依次为第0站至第n-1站。且己知第i站当前的人流量ai,拥挤段指一段站点个数大于等于K的连续站点区间,这段区间中的站平均人流量最 大。用1 (,为整数)表示从编号为的站点开始,编号为r的站点结束的站点区间,那么平均人 流量就等于编号在、r之间的站点ai的平均值。如果有多 个平均人流是最大的区间,取最长的那个。如果有多个平均人流量最大且最长的区间,取I最小的那个。
请你帮小程找到公交车线路当前的拥挤段[l,r]吧!
输入:
第一行两个正整数n(1<=n<=100),K(1<=K<=n)接下来行n个整数,第1个数ai表示当前第站的人流量(1<=ai<=1000)。
输出:
输出两个整数l.r,用一个空格隔开,表示拥挤段的开始站和结束站。
解题思路:题目不易看懂,看懂后可以剖析其实就是求解一个最长连续子序列,这个子序列的平均值最大。如果有两个子序列长度相等,输出靠前的部分。
方法:使用滑动窗口,不过滑动窗口要逐渐变大(第一层循环);每一个滑动窗口都需要遍历一次整个数组(第二层循环);需要统计滑动窗口中的平均值(第三层循环);每完成一次循环,需要更新区间的大小,区间的平均值,区间的首部和尾部。
代码:
#include<iostream>
#include<vector>
#include<limits.h>
#include<math.h>
using namespace std;
void FindDis(vector<int>& vec,int n,int k){
int begin = 0;
int end = k-1;
double max_av = 0;
int max_stat = k;;
int count_win = k;
while(count_win<=n){//第一层循环,用于改变滑动窗口的大小
int i=0;
int j = count_win-1;
while(j < n){//第二层循环,用于遍历整个数组
int i_temp = i;
int sum = 0;
while(i_temp<=j){//用于遍历局部
sum+=vec[i_temp++];
}
double av = (double)sum/(double)count_win;
if(av > max_av || (av == max_av && count_win > max_stat)){
begin = i;
end = j;
max_av = av;
max_stat = count_win;
}
i++;
j++;
}
count_win++;
}
cout << begin << " " << end << endl;
}
int main(){
int n,k;//输入
cin >> n >> k;
int stat_num = n;//车站个数
int a;//输入
vector<int> vec_station;
while(n--){
cin >> a;
vec_station.push_back(a);
}
FindDis(vec_station,stat_num,k);
return 0;
}