Luo Gu P3045 [USACO12FEB] cattle ticket Cow Coupons

Title: Luo Gu P3045 [USACO12FEB] cattle ticket Cow Coupons

Ideas:

greedy

Suppose you use up all the coupons, the only two decisions: the original purchase items not selected the lowest price; the lowest cost of returning a coupon with the current, and then buy discounted items not selected the lowest price .

Fallback (go back) operation can be achieved with a heap, concrete realization:

With three small root heap h1, h2, h3, unselected items are stored and numbered original, unselected price and number of items, the cost of selected items returned coupons.

Comparison of three stacks each stack top t1, t2, t3, if the current cost plus min (t1, t2 + t3) over m to break, or to select two decision and takes a small flicked top of the stack. Bool array by recording whether each item had been selected.

For convenience of implementation, may be initially added in the k 0 h3.


Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, int> node;
const int N = 1e5 + 5;
priority_queue< node, vector<node>, greater<node> > h1, h2;
priority_queue< ll, vector<ll>, greater<ll> > h3;
ll n, k, m, cnt, sum, p[N], c[N];
bool mark[N];
inline void In(ll &num) {
    register char c = getchar();
    for(num = 0; !isdigit(c); c = getchar());
    for(; isdigit(c); num = num * 10 + c - 48, c = getchar());
}
int main() {
    In(n); In(k); In(m);
    for(int i = 1; i <= n; ++i) {
        In(p[i]); In(c[i]);
        h1.push(make_pair(p[i], i));
        h2.push(make_pair(c[i], i));
    }
    for(int i = 1; i <= k; ++i) h3.push(0ll);
    while(!h1.empty()) {
        node t1 = h1.top(), t2 = h2.top();
        ll t3 = h3.top();
        if(mark[t1.second]) {
            h1.pop();
            continue;
        }
        if(mark[t2.second]) {
            h2.pop();
            continue;
        }
        if(t1.first < t2.first + t3) {
            if(sum + t1.first > m) break;
            ++cnt;
            h1.pop();
            sum += t1.first;
            mark[t1.second] = true;
        } else {
            if(sum + t2.first + t3 > m) break;
            ++cnt;
            h2.pop();
            h3.pop();
            sum += t2.first + t3;
            mark[t2.second] = true;
            h3.push(p[t2.second] - c[t2.second]);
        }
    }
    printf("%lld\n", cnt);
    return 0;
}

Guess you like

Origin www.cnblogs.com/yu-xing/p/11519717.html