K - Knapsack Collection Gym - 101482K(模拟)

13 篇文章 0 订阅

Gerald’s job is to welcome the teams for this year’s NWERC at the airport in Linköping. One of his duties is to stand at the luggage carousel and collect all the knapsacks that the teams are bringing. Gerald is a lazy person, so he just stands at the same position of the carousel and waits for bags to pass by so he can pick them up.
The baggage carousel consists of s luggage slots,
numbered in ascending order from 0 to s − 1. Since
the baggage carousel is cyclic, luggage slots s − 1 and
0 also lie side by side. The carousel turns in such a
way that if Gerald stands in front of slot i at some point in time, he will stand in front of slot
(i + 1) mod s one time unit later.
In the beginning Gerald prepares a huge baggage cart at some position and stands there to
wait for luggage. When a knapsack arrives in front of Gerald, he needs t time units to take it and put it on the baggage cart. After these t time units he is ready to pick up another knapsack. As long as there are remaining knapsacks on the luggage carousel, Gerald always takes the next one to arrive at his position as soon as he is ready after putting away the previous one.
Now Gerald wonders about the effect of his choice of position on the time it will take him to finish this task. It is up to you to help Gerald calculate the minimum, maximum, and average time to pick up all knapsacks, taken over all s possible slots, which can appear in front of Gerald after preparation. Time starts when he has prepared the baggage cart at some slot of the baggage carousel and ends after he has put the last knapsack on the cart.
Input
The input consists of:
• onelinewiththreeintegersn(1≤n≤2000),s(1≤s≤107)andt(1≤t≤107), where n is the number of knapsacks to pick up, s is the number of slots of the carousel, and t is the number of time units Gerald needs to pick up a knapsack from the carousel and put it on the cart;
• onelinewithnintegersk1,…,kn (0 ≤ ki ≤ s−1for1 ≤ i ≤ n),theslotsofthe knapsacks.
There may be several knapsacks stacked on top of each other in the same slot, but Gerald can still only pick up one knapsack at a time.
Output
Output three lines of output containing the minimum, maximum, and average time to pick up all the luggage, over all s positions. The average time should be output as a reduced fraction in the form p/q.
NWERC 2014 Problem K: Knapsack Collection 21
Picture by Bernhard J. Scheuvens via Wikimedia Commons.
Sample Input 1
Sample Output 1
7 10 10000000 0000001
70000001
70000009
350000027/5
Sample Input 2
Sample Input 3
Sample Output 2
Sample Output 3
10 10 3 0022446688
39 40 79/2
9 10000000 1 072345618
9
10000000
12500021249991/2500000

题意:
人坐在同一个节点,装一个物品时间为s。
机场取行李的地方是环形的,每秒走一个格子。
每个物品有对应出现的位置。
人坐在哪个位置取完物时间最大、时间最小、时间平均值。

思路:

  1. 假设确定了起点,那么很好办,每次找相距最近的一个点去拿物品即可。这个过程可以用multiset维护。
  2. 如果只算最小值,我们只需要算所有的有物品的格子。这不难思考。因为所有没有物品的格子,是要等一段时间才能到一个有物品的格子上。
  3. 如果算最大值,那么算上有物品的点取最大值,再算上每个物品后一个格子(等待最大时间到下一个物品)的最大值即可。
  4. 算总和,物品数目不大,这个过程是可以暴力维护的。而其他的点,其实可以用已经算出的点直接搞出来。假设 a [ i ] a[i] a[i]这个点的花费是 c o s t cost cost,那么 a [ i ] − 1 a[i]-1 a[i]1的值(假设这上面没有物品)就是 c o s t + 1 cost+1 cost+1,依次类推可以借助等差数列维护出所有没算出来的点。

ACNEW

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <set>
#include <queue>
#include <cmath>
#include <vector>
#include <map>
#include <ctime>

using namespace std;

typedef long long ll;
const int maxn = 2e3 + 7;

multiset<int>st;
int a[maxn];
int n,s,t;

ll gcd(ll n,ll m) {
    return m == 0 ? n : gcd(m,n % m);
}

ll cal(int pos) {
    multiset<int>nowst;
    nowst = st;
    ll ans = 0;
    for(int i = 1;i <= n;i++) {
        auto it = nowst.lower_bound(pos);
        if(it != nowst.end()) {
            int num = *it;
            ans += num - pos + t;
            pos = (num + t) % s;
        } else {
            it = nowst.begin();
            int num = *it;
            ans += s - 1 - pos + num + 1 + t;
            pos = (num + t) % s;
        }
        nowst.erase(it);
    }
    return ans;
}

void solve() {
    ll mi = 1e18,mx = 0,ans = 0;
    for(int i = 1;i <= n;i++) {
        if(i != 1 && a[i] == a[i - 1]) continue;
        ll tmp = cal(a[i]);
        mi = min(mi,tmp);
        mx = max(mx,tmp);
        ans += tmp;
        if(a[i] - a[i - 1] - 1 >= 1 && i != 1) {
            ll num = a[i] - a[i - 1] - 1;
            ans += tmp * num + (num + 1) * num / 2;
        }
    }
    
    ll num = s - 1 - a[n] + a[1];
    if(num >= 1) {
        ll tmp = cal(a[1]);
        ans += tmp * num + (num + 1) * num / 2;
    }
    
    for(int i = 1;i <= n;i++) {
        ll tmp = cal((a[i] + 1) % s);
        mx = max(mx,tmp);
    }
    
    ll Gcd = gcd(ans,s);
    ans /= Gcd;s /= Gcd;
    printf("%lld %lld %lld/%d\n",mi,mx,ans,s);
}

int main() {
    scanf("%d%d%d",&n,&s,&t);
    for(int i = 1;i <= n;i++) {
        scanf("%d",&a[i]);
        st.insert(a[i]);
    }
    sort(a + 1,a + 1 + n);
    solve();
    return 0;
}

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <string>
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <set>

using namespace std;

typedef long long ll;

const int maxn = 2005;
ll a[maxn];
multiset<ll>st;
ll n,s,t;
map<ll,ll>mp;

ll gcd(ll n,ll m) {
    return m == 0 ? n : gcd(m,n % m);
}

ll cal(ll tim) {
    multiset<ll>nowst;
    nowst = st;
    ll cost = 0;
    for(int j = 1;j <= n;j++) {
        auto it = nowst.lower_bound(tim);
        ll num;
        if(it == nowst.end()) {
            num = *nowst.begin();
            it = nowst.begin();
        }
        else {
            num = *it;
        }
        if(num >= tim) {
            cost += num - tim;
        }
        else {
            cost += (num - tim + s) % s;
        }
        cost += t;
        tim = num;
        tim = (tim + t) % s;
        nowst.erase(it);
    }
    return cost;
}

void solve() {
    ll ans = 0;
    ll mi = 1e18,mx = 0;
    ll cnta1 = 0;
    for(int i = 1;i <= n;i++) {
        ll tmp = cal(a[i]);
        if(i == 1) {
            cnta1 = tmp;
        }
        if(a[i] == a[i - 1]) continue;
        mi = min(tmp,mi);
        mx = max(tmp,mx);
        ans += tmp;
        if(a[i] - a[i - 1] >= 2 && i != 1) {
            ll num = a[i] - a[i - 1] - 1;
            ans += tmp * num + num * (num + 1) / 2;
        }
    }
    
    ll num = s - a[n] + a[1] - 1;
    ans += cnta1 * num + num * (num + 1) / 2;
    for(int i = 1;i <= n;i++) {
        if(mp[(a[i] + 1) % s] == 1) continue;
        ll tmp = cal((a[i] + 1) % s);
        mx = max(mx,tmp);
    }
    ll tmp = gcd(s,ans);
    s /= tmp; ans /= tmp;
    printf("%lld %lld %lld/%lld\n",mi,mx,ans,s);
}

int main() {
    a[0] = -1;
    scanf("%lld%lld%lld",&n,&s,&t);
    for(int i = 1;i <= n;i++) {
        scanf("%lld",&a[i]);
        st.insert(a[i]);
        mp[a[i]] = 1;
    }
    sort(a + 1,a + 1 + n);
    ll ans = 0;

    solve();
}

//7 10 10000000
//0 0 0 0 0 0 1

//7 100 10000000
//1 2 3 4 5 6 7

//7 9 10000000
//1 2 3 4 5 5 7
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值