修塔游戏题解

修塔游戏

http://www.nowcoder.com/questionTerminal/50f139741ff74f919bd4972f503631c2

思路,对高度为h的塔,都假定比它高和矮的塔向它靠拢,计算出最终达到共有k座高度为h的塔的最少操作次数,并最终计算所有高度的操作次数中的最小次数即为答案。
我使用map来保存每种高度的塔的数量。使用去重的vector保存排好序的塔。
同时使用四个vector保存计算所需要的变量。对于每一个高度的塔,算出左边都变为它的高度总共使用的操作次数,使用dp的方法累积计算,右边同理。其次还要计算每一个高度的塔左右两侧不同高度塔的数量。
最后只用一次遍历塔的数组,就能用这些状态算出每一种高度最少操作次数。
关键:每一种高度的塔的左侧操作次数是左侧都变为前一个高度的塔(towsLeftOp[i-1])再变为只比它高度少1的塔(+(tows[i]-tows[i-1]-1)*towsLeftNums[i-1])。右侧同理。
比较每一种高度的塔数量和它左右的塔数量,可以计算出最小需要发生变化的次数。

#include <algorithm>
#include <iostream>
#include <vector>
#include<map>
using namespace std;

int main()
{
    vector<int> tows;
    vector<int> towsLeftNums;
    vector<int> towsRightNums;
    vector<int> towsLeftOp;
    vector<int> towsRightOp;
    map<int,int>tmap;
    int n=0;int k=0;
    cin>>n>>k;
    for(int i=0;i<n;i++)
    {
        int t=0;cin>>t;
        tows.push_back(t);
        tmap[t]++;
    }
    sort(tows.begin(),tows.end());
    tows.erase(unique(tows.begin(), tows.end()), tows.end());
    for(int i=0;i<tows.size();i++)
    {
        if(i==0) 
            {
                towsLeftOp.push_back(0);
                towsLeftNums.push_back(tmap[tows[i]]);
            }
        else
        {
            towsLeftNums.push_back(towsLeftNums[i-1]+tmap[tows[i]]);
            int op=(tows[i]-tows[i-1])*towsLeftNums[i-1]+towsLeftOp[i-1];
            towsLeftOp.push_back(op);
        }    
    }
    for(int i=tows.size()-1;i>=0;i--)
    {
        if(i==tows.size()-1) 
        {
            towsRightOp.push_back(0);
            towsRightNums.push_back(tmap[tows[i]]);
        }

        else
        {
            towsRightNums.push_back(towsRightNums[tows.size()-i-2]+tmap[tows[i]]);
            int op=(tows[i+1]-tows[i])*towsRightNums[tows.size()-i-2]+towsRightOp[tows.size()-i-2];
            towsRightOp.push_back(op);
        }    
    }
    reverse(towsRightOp.begin(),towsRightOp.end());
    reverse(towsRightNums.begin(),towsRightNums.end());



    vector<int> ops;
    for(int i=0;i<tows.size();i++)
    {
        int leftOp=0;
        int rightOp=0;
        if(i>0)
        leftOp=towsLeftOp[i-1]+(tows[i]-tows[i-1]-1)*towsLeftNums[i-1];
        if(i<tows.size()-1)
        rightOp=towsRightOp[i+1]+(tows[i+1]-tows[i]-1)*towsRightNums[i+1];
        int leftTows=0;
        if(i>0)
        leftTows=towsLeftNums[i-1];
        int self=tmap[tows[i]];
        int rightTows=0;
        if(i<tows.size()-1)
        rightTows=towsRightNums[i+1];
        if(self>=k)
        {
            ops.push_back(0);
        }
        else
        {
            int times=0;
            if(self+leftTows<k&&self+rightTows<k)
            {
                times=leftOp+rightOp+k-self;
            }
            else if(self+leftTows>=k)
            {
                times=leftOp+k-self;
                if(self+rightTows>=k)
                {
                int times2=rightOp+k-self;
                if(times2<times)
                times=times2;
                }
            }
            else if(self+leftTows<k)
            {    
                times=rightOp+k-self;
            }
            ops.push_back(times);
        }

    }
    cout<<*min_element(ops.begin(),ops.end());
}
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务