有N个任务需要执行,第i个任务计算时占R[i]个空间,而后会释放一部分,
最后储存计算结果需要占据O[i]个空间(O[i] < R[i])。
例如:执行需要5个空间,最后储存需要2个空间。
给出N个任务执行和存储所需的空间,问执行所有任务最少需要多少空间。
输入
第1行:1个数N,表示任务的数量。(2 <= N <= 100000)
第2 - N + 1行:每行2个数R[i]和O[i],分别为执行所需的空间和存储所需的空间。(1 <= O[i] < R[i] <= 10000)
输出
输出执行所有任务所需要的最少空间。
输入示例
20
14 1
2 1
11 3
20 4
7 5
6 5
20 7
19 8
9 4
20 10
18 11
12 6
13 12
14 9
15 2
16 15
17 15
19 13
20 2
20 1
输出示例
135
分析:
本题可以看做是计算机的程序任务,在执行时需要一些内存,执行完成后只需要少部分内存存储着。
该题在贪心策略上,可以采用先排序,再扫描。其关键在于排序的方式上。
依题意,用r表示执行占用的空间,o表示存储时占用的空间。那么每执行完一次任务会释放掉r-o的空间。
假设所有的任务满足 r == o ,那么最优解就是o之和。然而事实是 r > o ,那么每次一执行某个任务,
就会先多调用 r - o 的空间。如图:灰黑色条代表执行时占用的空间,黄色代表执行完后存储空间。
实际上,每次释放的r-o的大小(灰色部分),就是总是在多占用内存的部分,
最上面的红线就是最优解了。
所以我们以灰色部分按从大到小排序,就是最优策略。可以尽量降低红线的位置
,排序工作做好了,贪心就算完成一半了,最后只需扫描一遍,记录下红线的最高位置即可
代码:
#include<stdio.h>
#include<algorithm>
#include<stdlib.h>
using namespace std;
int n;
struct node{
int run;//执行时的内存占用
int min;//执行完后打的占用
int away;//执行完此任务后释放掉的内存
}r[100100];
bool cmp(node a,node b)
{
return a.away>b.away;
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=0;i<n;i++)
{
scanf("%d%d",&r[i].run,&r[i].min);
r[i].away=r[i].run-r[i].min;
}
sort(r,r+n,cmp);//按释放内存的大小从大到小排序
int ram=0;
int temp=0;//实时内存占用
for(int i=0;i<n;i++)
{
temp+=r[i].run;
if(ram<temp)
ram=temp;
temp-=r[i].away;//释放掉一部分
}
printf("%d\n",ram);
}
return 0;
}