Wannafly挑战赛15 A-最小化价格(优先队列 / 迭代器+二分)

链接: https://www.nowcoder.com/acm/contest/112/A
来源:牛客网
最小化价格


时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
 64bit IO Format: %lld

题目描述


现有n组人,m个地点,给出每组人的人数,每个地点可容纳的最大人数和选择的价格   要求一种方式,使得每组人都到一个各不相同的地点,最小化选择的价格    每个队伍的人都要在同一个地方每个地方只能有一个队伍
输入描述:
第一行n,m第二行n个数,表示每组的人数接下来m行,每行两个数,表示可容纳的最大人数和选择的价格
输出描述:
输出最小化选择的价格,无解输出-1

示例1

输入
3 4
2 3 4
1 2
2 3
3 4
4 5

输出
12


备注:
所有数据小于1e5

解题思路:下面我给大家提供两种解法,若有更好的写法,欢迎留言!

解法1:优先队列,我们首先把每组的人数从小到达排个序,然后再把每个地点按照同样的方式排个序,然后从前往后枚举每个地点,如果大于该组的人数,就把这个地点的价格加入优先队列(并后移一个组),如果小于,那么还是加入(因为该地点一定满足以前装的组),然后弹出队列中最大的价格。最后求出队列中的总价格即可。

AC代码:(68ms)

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<queue>
#include<map>
#include<set>
#define bug printf("*********\n");
#define mem0(a) memset(a, 0, sizeof(a));
#define mem1(a) memset(a, -1, sizeofa());
#define in1(a) scanf("%d" ,&a);
#define in2(a, b) scanf("%d%d", &a, &b);
#define out1(n) printf("%d\n", n);
using namespace std;
typedef long long LL;
typedef pair<int, int> par;
const int mod = 1e9+7;
const int INF = 1e9+7;
const int N = 1000010;
const double pi = 3.1415926;
 
int n, m, a[100010];
 
struct node
{
    int num;
    int pic;
}e[100010];
 
bool cmp(node a, node b)
{
    return a.num < b.num;
}
 
int main()
{
    int x, y;
    while(~scanf("%d%d", &n, &m)) {
        LL ans = 0;
        priority_queue<int> q;
        for(int i = 0; i < n; i ++)
            in1(a[i]);
        sort(a, a+n);
        for(int i = 0; i < m; i ++)
            in2(e[i].num, e[i].pic);
        sort(e, e+m, cmp);
        int k = 0;
        for(int i = 0; i < m; i ++) {
            if(e[i].num >= a[k] && k < n) { //装得下
                q.push(e[i].pic);
                k ++;
            }else if(!q.empty()){ //装不下
                q.push(e[i].pic);
                q.pop();
            }
        }
        if(q.size() < n) printf("-1\n");
        else {
            while(!q.empty()) {
                ans += q.top();
                q.pop();
            }
            printf("%lld\n", ans);
        }
    }
    return 0;
}

解法2:迭代器+二分,同样我们先把每组人数放进一个multiset集合或者vector进行迭代,对于每个地点,我们按照价格从小到达排序,然后枚举每个地点,找到刚好小于等于该地点的人数的那个组,加上这个地点的价格,并把那个组删掉,最后如果没有剩余的组就输出总花费,否则-1。

AC代码: (vector的写法208ms)
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<queue>
#include<map>
#include<set>
#define bug printf("*********\n");
#define mem0(a) memset(a, 0, sizeof(a));
#define mem1(a) memset(a, -1, sizeofa());
#define in1(a) scanf("%d" ,&a);
#define in2(a, b) scanf("%d%d", &a, &b);
#define out1(a) printf("%d\n", a);
#define out2(a, b) printf("%d %d\n", a, b);
using namespace std;
typedef long long LL;
typedef pair<int, int> par;
const int mod = 1e9+7;
const int INF = 1e9+7;
const int N = 1000010;
const double pi = 3.1415926;
 
int n, m, x;
 
struct node
{
    int num;
    int pic;
    bool operator<(const node a) const {
        return this->pic < a.pic;
    }
}e[100010];
 
vector<int> G;
vector<int>::iterator it;
 
int main()
{
    while(~scanf("%d%d", &n, &m)) {
        G.clear();
        long long ans = 0;
        int flag = 0;
        priority_queue<node> q;
        for(int i = 0; i < n; i ++) {
            in1(x);
            G.push_back(x); //这样的加入方式不能自动排序
        }
        sort(G.begin(), G.end());
        /*
        加入迭代器自动排序
        for(int i = 0; i < n; i ++) {
            in1(x);
            it = upper_bound(G.begin(), G.end(), x);
            G.insert(it, x);
        }
        */
        for(int i = 0; i < m; i ++) {
            in2(e[i].num, e[i].pic);
        }
        sort(e, e+m);
        for(int i = 0; i < m; i++) {
            it = upper_bound(G.begin(), G.end(), e[i].num);
            if(it != G.begin()) {
                it --;
                ans += e[i].pic;
                G.erase(it);
            }
        }
        if(G.empty()) {
            out1(ans);
        }else printf("-1\n");
    }
    return 0;
}

AC代码: (multiset+二分119ms) 推荐这种写法,比vector简单
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<queue>
#include<map>
#include<set>
#define bug printf("*********\n");
#define mem0(a) memset(a, 0, sizeof(a));
#define mem1(a) memset(a, -1, sizeofa());
#define in1(a) scanf("%d" ,&a);
#define in2(a, b) scanf("%d%d", &a, &b);
#define out1(a) printf("%d\n", a);
#define out2(a, b) printf("%d %d\n", a, b);
using namespace std;
typedef long long LL;
typedef pair<int, int> par;
const int mod = 1e9+7;
const int INF = 1e9+7;
const int N = 1000010;
const double pi = 3.1415926;

int n, m, x;

struct node
{
    int num;
    int pic;
    bool operator<(const node a) const {
        return this->pic < a.pic;
    }
}e[100010];

multiset<int> s;
multiset<int>::iterator it;

int main()
{
    while(~scanf("%d%d", &n, &m)) {
        s.clear();
        int ans = 0;
        for(int i = 0; i < n; i++) {
            in1(x);
            s.insert(x);
        }
        for(int i = 0; i < m; i ++)
            in2(e[i].num, e[i].pic);
        sort(e, e+m);
        for(int i = 0; i < m; i ++) {
            it = s.upper_bound(e[i].num);
            if(it != s.begin()) {
                it --;
                ans += e[i].pic;
                s.erase(it);
            }
        }
        if(s.empty()) prinft("%d\n", ans);
        else printf("-1\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/i_believe_cwj/article/details/80293350
今日推荐