招商银行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;
}
全部评论
显示不太对,是n=4,k=4,数据是1 2 2 3,结果应该是2,但是贪心策略的结果是4
2 回复 分享
发布于 2020-04-29 14:15
测试用例不全面,简单给个数据 4 4 1 2 2 3 贪心策略结果应该不对
点赞 回复 分享
发布于 2020-04-29 13:54
好多用贪心偷跑的。这个题的测试数据也太不负责了。看榜上好多提交连楼上的那个样例都过不了的都能AC。
点赞 回复 分享
发布于 2020-04-29 17:45
这复杂度也能过?
点赞 回复 分享
发布于 2021-04-27 15:25

相关推荐

程序员鼠鼠_春招版:都很烂大街,rpc也基本没人问,考研吧,不然就包装一段实习再去
点赞 评论 收藏
分享
02-18 21:55
门头沟学院 Java
点赞 评论 收藏
分享
评论
点赞
5
分享

创作者周榜

更多
牛客网
牛客企业服务