现有 n 件任务和无限多台的机器,任务可以在机器上得到处理。每件任务的开始时间为 si,完成时间为 ei,[si, ei]为处理任务的时间范围。2 个任务重叠是指 2 个任务的时间范围有重叠。例如,[1, 4]与[2, 4]重叠,[1, 4]与[4, 7]重叠。一个可行的任务分配是指在分配中没有 2 件重叠的任务分配给同一台机器。
对于给定的 n 件任务,编程计算使用机器数最少的可行分配方案。
第1行只有一个整数n(n<=1000,表示任务的总数。接下来有n行,每行2个整数si,ei分别表示任务的开始时间和完成时间,其中0<=si<=ei<10000.
计算出的最少使用的机器数。
3
1 4
2 5
5 7
2
tianzuwei
思考:用N个任务,很多的机器,每一个任务有一个开始和结束的时间[si, ei],任务的完成时间是固定的,也是会有重叠的部分,也就是在3点的时候,可能有[1,4],[2,4]两个任务需要同时完成,现在问完成这么多的任务最少需要多少的机器。假如给每一个任务都分配一个机器的话,那么至多也就是需要N个机器,但是很明显的地方在于一台机器可以完成[1,3], [4,6] 等多个不重叠的任务,所以完成N个任务的最少机器,就是在某一个时间点上面任务重叠最多的所需要的机器。
程序大致解析: 以数组下标作为时间点,数组具体值作为重叠任务数,初始值为0,每输入一个任务,就在该任务完成的时间上面所有的时间节点+1,最后遍历所得的数组,找出最大的元素即所求。具体见下:
#include
#define maxx 10001
using namespace std;
int num[maxx];
int main()
{
//freopen("in.txt","r",stdin);
int n, i, mx, x, y, t;
while(cin >> n)
{
t = 0;
memset(num, 0 ,sizeof(num));
for(i = 0; i < n; i++)
{
cin >> x >> y;
for(x; x <= y; x++)
num[x]++;
if(t <= y) t = y;
}
mx = 0;
for(i = 0; i <= t; i++)
if(mx < num[i]) mx = num[i];
cout << mx << endl;
}
fclose(stdin);
return 0;
}
补充:后面学习当中,发现更加好的算法,上面的算法时间复杂度为O(n^2),可以用差分数组的思想,优化到O(n)的时间复杂度。见下面代码:
#include
using namespace std;
#define INF 0x3f3f3f3f
const int N = 100000 + 10;
int m, q;
int a[N], d[N], sum[N];
int main()
{
//freopen("in.txt", "r", stdin);
int n;
while (scanf("%d", &n) != EOF)
{
memset(a, 0, sizeof(a));//初始化都为0
int l, r;
memset(d, 0, sizeof(d));
d[1] = a[1];//特殊处理第一个数
for (int i = 0; i < n; i++)
{
scanf("%d%d", &l, &r);
d[l] += 1;
d[r+1] -= 1;
}
memset(sum, 0, sizeof(sum));
for (int i = 1; i <= n; ++i)
{
sum[i] = sum[i-1] + d[i]; //求d[i]前缀和, 也就是修改后的a[i]
}
int maxn = 0;
for (int i = 1; i <= n; ++i)
{
if(maxn < sum[i]) maxn = sum[i];
}
cout << maxn << endl;
}
fclose(stdin);
return 0;
}