先考虑第一问:
贪心。如何贪心呢? 看成时间块的插入。 插入1号机器的话,时间条长度为a[1], 插入2号机器,时间条长度为a[2].
类似俄罗斯方块一样~~! 然后想办法插入,使得最高的那个最低。
x[i]表示,当前插了一些时间条后,第i个机器的时间条高度。 (看成俄罗斯方块!插时间条,也就是只有俄罗斯方块的很长的那个长条。) x[i]就是当前第i个位置的高度(俄罗斯方块是有高度的……)
显然对于i机器而言,每次插入的时间条长度都是a[i]
要插一个时间条,穷举一下所有可以插的位置,看看插入哪个位置后,高度最低。 也就是 {x[i] + a[i]}最小,就插在i的位置。
代码如下: m1表示有m1个机器
inline int get(int a[], int x[], int m1, int q1[])
{
int ans1(0);
for (int i = 1; i <= n; ++ i)
{
int tmp = 0x7fffffff, pos1, pos2;
for (int j = 1; j <= m1; ++ j)
if (a[j] + x[j] < tmp)
{
tmp = a[j] + x[j];
pos1 = j;
}
x[pos1] = tmp;
q1[i] = tmp;
if (tmp > ans1) ans1 = x[pos1];
}
return ans1;
}
==========
官方题解翻译:
你可以贪婪的决定第k个job可以被A机器完成的最早的时间。(显然这题就是贪心啦!)
对于每个机器,时刻注意它什么时候完成了它正在做的任务。(显然,一完成一个任务,立马就投入下一个任务啊……)
完成接下来工作所需要的时间,是当前已经工作的时间加上对于这个机器而言,处理一次所要花费的时间.
如何决定第k个工作在哪个机器呢? 选择能最先完成它的机器! 然后给这个机器安排第k个工作。接着更新这个机器已经工作的时间。
同样的,决定第k个工作什么时候从被A机器完成,到可以被放入B机器。 对于B机器而言,最先完成的工作是从所有工作结束的地方开始测量(这句话翻译的有点奇怪,换一个方式表达: 我
们可以假设在T时间完成所有任务, 那么我们就让每个工作在B机器都在第T时间恰好完成)。这类似于对于A而言翻转过来的过程,每一个被A机器完成的工作,还必须被B机器“拆解”。
一旦这2个计算已经被计算完,并且数组被排序完成后,你最终得到的图片应该和这个类似:
【不懂?其实先看图,再看图后面的文字。再加强理解】
每一行代表一个工作的行为。绿色和蓝色是A机器,黄色,蓝绿色(cyan),紫色代表B的机器。一个红色的行表示这一段时间这个工作没有进行。左边部分对应A工作,在每一行末尾的地方,
是第k个工作完成的时间。(图对应样例数据)
右边部分对应B工作,每一行最开始的地方是 第K个工作最早的可以在B工作结束的时候开始。白色的空格代表空闲(slack)时间,这个时间工作都在运转中。
最好的选择是让最早完成A工作,匹配上最迟完成B工作,第二个完成A工作的,匹配第二迟完成B工作的。在这些时间中取得最大值。这对应让图两边的图形移动,相碰撞。(有一个工作没有空闲(slack)时间)
我的方法:我没有用白色空格的时间,我是穷举结束的时间,然后判定是否合法- - 之前没看题解,没想到到直接碰撞的方法。
/*
TASK:job
LANG:C++
*/
#include <cstdio>
int n;
int m1, m2;
int a[50]={0}, b[50]={0};
int x[50]={0}, y[50]={0}, tot=0;
int q1[1010], q2[1010];
void init()
{
scanf("%d%d%d", &n, &m1, &m2);
for (int i = 1; i <= m1; ++ i) scanf("%d", &a[i]);
for (int i = 1; i <= m2; ++ i) scanf("%d", &b[i]);
}
inline int get(int a[], int x[], int m1, int q1[])
{
int ans1(0);
for (int i = 1; i <= n; ++ i)
{
int tmp = 0x7fffffff, pos1, pos2;
for (int j = 1; j <= m1; ++ j)
if (a[j] + x[j] < tmp)
{
tmp = a[j] + x[j];
pos1 = j;
}
x[pos1] = tmp;
q1[i] = tmp;
if (tmp > ans1) ans1 = x[pos1];
}
return ans1;
}
inline bool check(int k)
{
int j = n;
for (int i = 1; i <= n; ++ i)
{
int tmp = q1[i];
if (k - q2[j] < tmp) return false;
--j;
}
return true;
}
void doit()
{
int ans1, ans2;
ans1 = get(a, x, m1, q1);
ans2 = get(b, y, m2, q2);
printf("%d ",ans1);
int L = 0,R = 14000, mid;
while (L + 1 < R)
{
mid = (L + R) / 2;
if (check(mid)) R = mid;
else L = mid;
}
printf("%d\n",R);
}
int main()
{
//freopen("job.in","r",stdin);
//freopen("job.out","w",stdout);
init();
doit();
return 0;
}
/**
2 2 2
3 5
8 5
*/