Problem description
小伟报名参加中央电视台的智力大冲浪节目。本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者m元。先不要太高兴!因为这些钱还不一定都是你的?!接下来主持人宣布了比赛规则:
首先,比赛时间分为n个时段(n≤500),它又给出了很多小游戏,每个小游戏都必须在规定期限ti前完成(1≤ti≤n)。如果一个游戏没能在规定期限前完成,则要从奖励费m元中扣去一部分钱wi,wi为自然数,不同的游戏扣去的钱是不一样的。当然,每个游戏本身都很简单,保证每个参赛者都能在一个时段内完成,而且都必须从整时段开始。主持人只是想考考每个参赛者如何安排组织自己做游戏的顺序。作为参赛者,小伟很想赢得冠军,当然更想赢取最多的钱!注意:比赛绝对不会让参赛者赔钱!
Input format
共4行。
第1行为m,表示一开始奖励给每位参赛者的钱;
第2行为n,表示有n个小游戏;
第3行有n个数,分别表示游戏1到n的规定完成期限;
第4行有n个数,分别表示游戏1到n不能在规定期限前完成的扣款数。
Output format
仅1行。表示小伟能赢取最多的钱。
Algorithm design
贪心算法
Problem analysis
不难想到尽量把每一个活动都放在结束前一秒完成,为其他活动争取更大的空间
这只是一个理想的情况,有些活动不得不放弃,所以要优先完成扣款多的游戏
既然如此,把扣款多的游戏从多到少都尽量放在结束前1秒,把玩游戏的时间标记,如果这个时间已经被占用,就往前移,直到无法放置,这个贪心法则绝对是正确的,因为每个游戏最多占用1秒,一旦会导致后面某些游戏玩不了,那么即使不玩这个游戏,后面的游戏也最多只能玩1个,且扣更多的款
得证贪心法则:按游戏扣款从多到少按时间从后往前完成
Source code
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 int m,n,f[501]; 6 pair <int,int > game[501]; 7 8 int main() 9 { 10 freopen("test.in","r",stdin); 11 freopen("test.out","w",stdout); 12 cin>>m>>n; 13 for(int i=1;i<=n;i++) 14 cin>>game[i].second; 15 for(int i=1;i<=n;i++) 16 cin>>game[i].first; 17 sort(game+1,game+n+1); 18 for(int i=n;i>=1;i--) 19 { 20 int sub=game[i].second-1; 21 while(f[sub]&&sub)sub--; 22 if(f[sub]) 23 { 24 m-=game[i].first; 25 continue; 26 } 27 f[sub]=1; 28 } 29 cout<<m<<endl; 30 return 0; 31 }