链接:
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
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; }