一道贪心+排序的题目,本题的难点在于选了一个比赛后该如何进行处理才能保证剩下的最大的依次能够
被处理直至结束。
很多人直接能想到的就是直接对价值排序,先将价值高的做了。因此处理顺序也就是按照排序过后的这个
顺序进行的。下面就是本题解题的关键:
按照题目给的样例:
10000 7 4 2 4 3 1 4 6 70 60 50 40 30 20 10
题目已经从大到小排好序了,首先对价值最高的进行处理,也就是将第四个时间段占用了,那么我们就要将这个
阶段标记好。那么之后的其他阶段都不能占用这个点了。
接着对于第二个,也就是将第二个阶段占用。最关键的
一点,处理第三个时,由于第一个游戏已经把第四个阶段占用了,那么这个只能往前数(因为这是可以往前来做的),
然后就是第四个游戏,它在第三个时间段,又由于第三个游戏已经把第三个阶段占用了,只能再往前查一个,而第二个阶段
又被第二个游戏给占用了,那么它只能占用第一个时间段。
到此为止前四个时间段都被占用了,对于下一个游戏,由于它
只能占用小于等于第三个时间段的,而又由于前四个时间段都已经被占用完,那么它就只能被放弃了。
接下来同理。
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 5 const int N = 510; 6 bool vis[N]; 7 int cnt[N]; 8 struct Node{ 9 int date, value; 10 }node[N]; 11 12 bool cmp(Node a, Node b){ 13 return a.value >= b.value; 14 } 15 int main(){ 16 int n, money, ans = 0, sum = 0; 17 cin >> money >> n; 18 for(int i = 0; i <= n; i ++) 19 cnt[i] = i; 20 for(int i = 0; i < n; i ++) 21 cin >> node[i].date; 22 for(int i = 0; i < n; i ++){ 23 cin >> node[i].value; 24 sum += node[i].value; 25 } 26 sort(node, node + n, cmp); 27 for(int i = 0; i < n; i ++){ 28 if(!vis[cnt[node[i].date]] && cnt[node[i].date] > 0){ 29 //如果这个时间段没被占用,就占用,标记一下,然后能使用这个 30 //阶段的(或者说同一个阶段的)都往前指一格。 31 vis[cnt[node[i].date]] = true; 32 cnt[node[i].date] --; 33 ans += node[i].value; 34 }else{ 35 int j = i; 36 while(vis[cnt[node[j].date]] && cnt[node[j].date] > 0){ 37 //当后面的同一时间点的发现这个时间点被前面同一时间点的占用了,那么 38 //就不断往前指,如果在>0之前能找到,就占用并标记,如果<=0就 39 //代表不能满足了,退出。 40 cnt[node[j].date] --; 41 if(!vis[cnt[node[j].date]] && cnt[node[j].date] > 0){ 42 vis[cnt[node[j].date]] = true; 43 cnt[node[j].date] --; 44 ans += node[j].value; 45 break; 46 } 47 } 48 } 49 } 50 cout << money - sum + ans << endl; 51 system("pause"); 52 return 0; 53 }