招商银行2020FinTech精英训练营-研发赛道 C 修塔游戏
修塔游戏
https://ac.nowcoder.com/acm/contest/5246/C
题目描述
小招正在玩一款修塔游戏:系统中有n座高塔,每座高塔由若干个高度相同的方块堆砌而成。修塔游戏的规则为:
(1)每次从最高塔的塔尖拿走一个方块
(2)每次在最低塔的塔尖堆砌一个方块
小招每次只能完成上述两个动作中的一个动作。游戏的目标是使n座高塔中至少有k座高塔的高度相同,请问小招最少需要多少次才能完成游戏。
输入描述:
输入共有2行,第一行为n和k(1≤k≤n≤200000 ),第二行为n座塔的高度组成的数组 a1, a2, ...an(1≤aj≤10000)。
输出描述:
输出值为最少需要多少次动作才能完成游戏。
示例1
输入
6 5
1 2 2 4 2 3
输出
3
思路
假设最终操作完成k座高塔高度为h,则在操作之前的高塔中,存在高度小于h、等于h、大于h三类,每一类数量分别是n_neg,n_zero,n_pos。若n_zero大于等于k,则不需要任何操作。其他情况下,根据k的大小,在高度小于h和大于h的高塔中进行操作最终满足要求。存在一下几种情况
- 只操作高度小于h的塔
- 只操作高度大于的塔
- 高度小于h的塔都需要操作,又可以分为
- 先操作高度小于h的塔,再操作高度小于h的塔
- 先操作高度小于h的塔,再操作高度小于h的塔
所有情况取最小值得到在这个h下的最小操作次数,h可以取得范围是0~最高塔的高度,然后在h的这个范围内,取操作数最小值。
代码
#include<iostream>
#include<algorithm>
#include<climits>
using namespace std;
int count_step(vector<int> &a_sorted, int k){
//vector<int> a_neg, a_pos, a_zero;
int n_neg = 0, n_pos = 0, n_zero = 0;
int orig_step_lf = 0, orig_step_hf = 0;
for(auto ele:a_sorted){
if(ele < 0){
//a_neg.push_back(abs(ele+1));
orig_step_lf+=abs(ele+1);
n_neg++;
}
else if(ele == 0){
//a_zero.push_back(ele);
n_zero++;
}
else{
//a_pos.push_back(ele);
orig_step_hf+=abs(ele-1);
n_pos++;
}
}
if(n_zero >= k)
return 0;
//Lower First
int step_lf = 0;
if(n_neg > 0){
if(n_neg >= k - n_zero)
step_lf = orig_step_lf + k - n_zero;
else{
step_lf = orig_step_lf + orig_step_hf + k - n_zero;
}
}
else{
step_lf = orig_step_hf + k - n_zero;
}
//Higer First
int step_hf = 0;
if(n_pos > 0){
if(n_pos >= k - n_zero)
step_hf = orig_step_hf + k - n_zero;
else
step_hf = orig_step_hf + orig_step_lf + k - n_zero;
}
else{
step_hf = orig_step_lf + k - n_zero;
}
return min(step_hf, step_lf);
}
int main()
{
int n,k;
cin>>n>>k;
vector<int> a(n);
for(int i=0;i<n;i++){
cin>>a[i];
}
int max = *max_element(a.begin(),a.end());
int min_step = INT_MAX;
for(int i=0;i<=max;i++){
vector<int> dif(n);
for(int j=0;j<n;j++)
dif[j] = a[j]-i;
//a_sorted = sorted(dif)
int step = count_step(dif, k);
min_step = min(min_step, step);
}
cout<<min_step;
return 0;
}

美的集团公司福利 747人发布