您的位置:首页 > 其它

gdoi2009中山市选T2 小球

2016-08-07 11:10 141 查看
问题描述:
给定n个不同颜色的球,每个球都有一个分数,同时有m个瓶子,每个瓶子都有固定的容量。现在,你必须把球放到瓶子里面。请编程计算最多能放多少个球到这些瓶子里。
输入格式:
输入包含多组数据。
每组数据的第一行为两个整数n, m,分别表示球的个数和瓶子的个数。
接下来的n行,每一行包含一个整数p,表示相应的球的分数。
接下来的m行,每一行包含两个整数c和q, 分别表示每个瓶子的容量(最多能装多少个球)和分数上界(放进该瓶子的每个球的分数都不能超过去q)。
当输入n,m均为0时,表示输入结束。
输出格式:
对于每组数据,输出两个整数B和S,分别表示总共能放进瓶子里的球的最大数目,以及在这个前提下,放进瓶子里面的所有球的最大分数总和。B和S以空格隔开,每组答案独占一行。
输入样例:
输出样例:
2 1
2
3
1 2
2 2
4
5
2 4
2 5
0 0
1 2
2 9
数据范围:
对于20%的数据,有1<=n<=10,0<=m<=10。
对于40%的数据,有1<=n<=50,0<=m<=50。
对于全部的数据,有1<=n<=200,0<=m<=200,1 <= p <= 10^6, 0 <= c <= 200, 1 <= q <= 10^6.
================================================================这道题一开始也没思路,想写暴搜骗个20分.但是旁边的同学又在讨论,说是贪心,于是改从贪心的角度出发来思考,发现确实可行,原则就是把尽可能高分的球放在尽可能大的瓶里面,那显然要先把球的分数和瓶的分数上限排个序,然后单调队列搞一下,就可以了.感觉自己描述得不是很清楚,还是把solution放上来:本题的标准解是贪心。因为小球本身没有体积差别,取哪个小球都只是占用相同的瓶子的体积,所以可以在所有小球中找出分值最大的那个球,看能不能找到可以放它的瓶子,如果有多个瓶子可以放这个小球,就将这个小球放在限制值最小的那个瓶子里,如果没有瓶子可以放,那么就把这个小球丢弃掉,然后用相同的方法在余下的小球中找一个最大的,放入可以放的瓶子中容量限制最小的,依次类推直到所有小球处理完。 为了方便小球的查找和瓶子的查找操作,可以先对小球按分数值进行排序,对瓶子按分数上限进行排序,然后将小球由分数从高到低进行取放尝试,对瓶子按容量限制从小到大放置,问题得解!这里排序可以采用快排,以提高算法效率。据说此题还可以用二分图来解,不过我不会.会的人,你厉害.
#include<algorithm>
#include<fstream>
#include<functional>
using namespace std;
const int maxn = 205;
struct Tnode {
int volume, score_limit;
bool operator<(const Tnode x)const {
return score_limit > x.score_limit;
}
} bottle[maxn];
ifstream fin("ball.in");
ofstream fout("ball.out");
int n, m, score[maxn];
int main() {
while(1) {
fin >> n >> m;

if(n == 0 && m == 0)break;

for(int i = 0; i != n; ++i)fin >> score[i];

for(int i = 0; i != m; ++i)fin >> bottle[i].volume >> bottle[i].score_limit;

sort(score, score + n, greater<int>());
sort(bottle, bottle + m);
int cnt = 0, sum = 0;
int i = 0, j = 0, put_in = 0;

while(i != n && j != m) {
if(score[i] > bottle[j].score_limit) {
++i;
continue;
}

if(put_in < bottle[j].volume) {
++put_in;
++cnt;
sum += score[i++];
} else {
put_in = 0;
++j;
}
}

fout << cnt << " " << sum << endl;
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: