[NOIP模拟](三)T1-太空电梯

[NOIP模拟] (三)T1-太空电梯


阅读本文推荐BGM: いつも何度でも(永远同在)(Cover 千与千寻) - Keyshawn Binean

border="0" width="330" height="86" src="//music.163.com/outchain/player?type=2&id=492550872&auto=1&height=66">

问题描述 :

    为了解决日渐增长的人口问题, Mstdream 率领一个小组到达火星开发新的居住地。
    地球到火星有一架太空电梯,电梯一次最多承载 2 个人,最大载重为 k, 小组一共有 n 个人,第 i 个人重量为 vi 。人们排成一队等候上电梯。
   上电梯的规则是这样的:
        1. 如果电梯是空的,下一个人可以上去
        2. 如果电梯有一个人,并且下一个人上电梯不会超重,下一个人可以上去,否则太空电梯会将前一个人载到火星后返回接下一个人
        3. 如果电梯有两个人,下一个人不能上去。

    由于管理出现了失误! 人们排队的顺序发生了变化.假设人们的顺序是未知的, Mstdream 想知道,太空电梯最多会跑多少趟?


输入格式 :

第一行两个数 n,k
第二行开始 n 行,每行一个数代表 vi

输出格式 :

输出一个数,代表最坏情况下太空电梯需要跑的趟数

Sample Input

6 6
1
2
3
3
4
5

Sample Output

5

Hint

最坏情况下排队的顺序如下:(2)(5 1)(3)(4)(3)


数据规模

50%   n <= 10
100%  n <= 100000,  k <= 1000000000,  vi <= k


谈一谈我的想法 :

    这种题在考场上一定要写对拍, 这种简单题自己是很容易考虑掉一些情况的, 这是我在考场上血的教训, 由于情况考虑掉了只有30分, 本来单场可以拿很高的分的。说说做法吧, 对于每一个数只需要找到与它相加大于 K 的最小数就可以了, 弄个队列可以很轻松的实现。

题解 :

    对于读入的序列直接 sort 一遍, 从头扫直接找队尾的元素, 当前最尾的元素满足与之相加大于 k, 也就是 a[head] + a[tail] > k, 就将队尾数加到那一位数的旁边, 如果不满足就将其加入尾队列, 因为其无论在什么位置都不会影响最优答案。最后统计结束。

下面贴出代码 :

同志们一定要考虑在统计答案时, 队列里还有一个数时要加一。 不然只有三十分。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <ctime>
#include <map>
#include <vector>
using namespace std;

inline int read() {
    int i = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1; ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();
    }
    return i * f;
}

const int MAXN = 1e5 + 10;
struct point {
    int head, tail;
    long long w;
};
point a[MAXN];
long long k, hou[MAXN], now[MAXN];
int n, tailh, tailn, ans;

inline bool comp(const point & x, const point & y) {
    return x.w < y.w;
}

inline void solve() {
    int l = 0, c = 0;
    for(int i = 1; i <= tailn; ++i) {
        //cout<<l<<' '<<c<<endl;
        if(l + now[i] <= k && c <= 1) {
            l += now[i];
            ++c;
        }  
        else 
            if(l + now[i] > k)
                l = now[i], c = 1, ++ans;
        if(c == 2) 
            l = 0, c = 0, ++ans;
    }
    if(c > 0) ++ans;
}

int main() {
    n = read(); cin>>k;
    for(int i = 1; i <= n; ++i) cin>>a[i].w;
    sort(a + 1, a + n + 1, comp);
    int h = n, tou = 0, q;
    for(int i = 1; i <= h; ++i) {
        if(i != h) {
            if(a[i].w + a[h].w > k) {
                if(!tou) {
                    tou = i;
                    a[i].head = i; a[i].tail = h;
                    a[h].head = i; q = h; --h;
                }
                else {
                    a[i].head = q; a[q].tail = i;
                    a[i].tail = h; a[h].head = i;
                    q = h; --h;
                }
            }
            else 
                hou[++tailh] = i;
        }
        else {
            a[i].head = q;
            a[q].tail = i;
        }
    }
    int ow = tou;
    while(true) {
        now[++tailn] = a[ow].w;
        if(a[ow].tail) ow = a[ow].tail;
        else break;
    }
    for(int i = 1; i <= tailh; ++i)
        now[++tailn] = a[hou[i]].w;
    solve();
    cout<< ans;
}

本题结束

是不是该犒劳自己一曲音乐呢:Just the Way You Are - Bruno Mars

border="0" width="330" height="86" src="//music.163.com/outchain/player?type=2&id=5093684&auto=0&height=66">

感谢阅读本篇文章,喜欢的话,点个赞吧,你的鼓励就是我最大的动力

有什么意见,尽情发表吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值