https://www.51nod.com/Challenge/Problem.html#!#problemId=2070
小伟报名参加中央电视台的智力大冲浪节目。本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者m元。先不要太高兴!因为这些钱还不一定都是你的?!接下来主持人宣布了比赛规则:
首先,比赛时间分为n个时段(n≤500),它又给出了很多小游戏,每个小游戏都必须在规定期限ti前完成(1≤ti≤n)。如果一个游戏没能在规定期限前完成,则要从奖励费m元中扣去一部分钱wi,wi为自然数,不同的游戏扣去的钱是不一样的。现在你要设计方法,使得你能得到最多的奖励。
输入
输入共 4 行
第 1 行为 m ,表示一开始奖励给每位参赛者的钱;
第 2 行为 n,表示有 n 个小游戏;
第 3 行有 n 个数,分别表示游戏 1 到 n 的规定完成期限;
第 4 行有 n 个数,分别表示游戏 1 到 n 不能在规定期限前完成的扣款数。
输出
输出文件仅 1 行。表示小伟能赢取最多的钱。
输入样例
10000
7
4 2 4 3 1 4 6
70 60 50 40 30 20 10
输出样例
9950
方法一:按截止时间排序
考虑两个游戏,如果完成时间都在规定期限之前,顺序是无所谓的。如果新加的游戏使得完成时间大于规定期限那么选择一个 wi 小的删去,可能是删掉新加入的游戏也可能是已加入的
方法二:按收益排序
对于两个游戏,首先尝试收益高的(截止时间 = t ),是否能安排上。如果 ( t-1 , t )时间段可以用则安排上并标记,否则尝试 (t-2 , t-1)时间段,依序往下,如都已被占用 ,则放弃该活动。 不能安排的活动不能替代已安排的活动。
过程中用并查集管理时间段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <bits/stdc++.h> using namespace std; #define MAX 500+10 pair<int ,int > a[MAX]; priority_queue<int> p; int n,m,ans; int main(){ freopen("in","r",stdin); scanf("%d\n%d",&m,&n); for(int i=0;i<n;i++) scanf("%d",&a[i].first); for(int i=0;i<n;i++) scanf("%d",&a[i].second); sort(a,a+n); for(int i=0;i<n;i++){ p.push(-a[i].second); if(p.size()>a[i].first){ ans+=p.top(); p.pop(); } } printf("%d",m+ans); return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include <bits/stdc++.h> using namespace std; const int MAX=500+10; pair<int ,int > a[MAX]; int f[MAX],m,n,ans,t=0; int find(int x){ return x==f[x]? x :f[x] = find(f[x]); } int cmp (const pair<int ,int > &x, const pair<int ,int >&y){ return x.second>y.second; } int main(){ freopen("in","r",stdin); scanf("%d%d",&m,&n); for(int i=0;i<n;i++){ scanf("%d",&a[i].first); if(a[i].first > n) f[a[i].first] =n; } for(int i=0;i<n;i++) scanf("%d",&a[i].second); for(int i=0;i<=n;i++) f[i]=i; sort(a,a+n,cmp); for(int i=0;i<n;i++){ int t= find(a[i].first); if(t>0) f[t] = f[t-1]; else ans+=a[i].second; } printf("%d",m-ans); return 0; }
|