[NOIP模拟] (三)T1-太空电梯
border="0" width="330" height="86" src="//music.163.com/outchain/player?type=2&id=492550872&auto=1&height=66">阅读本文推荐BGM: いつも何度でも(永远同在)(Cover 千与千寻) - Keyshawn Binean
问题描述 :
为了解决日渐增长的人口问题, 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">感谢阅读本篇文章,喜欢的话,点个赞吧,你的鼓励就是我最大的动力
有什么意见,尽情发表吧。