百度之星区域赛第一题——平衡负载题解

   好久没做算法题,现在依稀记得当年刷题的灵感和激情,怀念那段时光,怀念那个时候的自己。曾经在一个学校的oj上看到过一篇类似这样的文章 —— 《弱校的ACMer奋斗史》心里思绪万分,因为他写出了我们对算法对ACM的情节,自己心里有很强烈的共鸣。因准备不充分,外加当时我们还没开算法这门课程导致了一系列的事情,11年省赛的失利,小组的解散..........种种压力之下我选择退出ACM转投javaEE。现在回想起来对于当时的选择我并不后悔,但是在我心里永远是算法第一,Java和c第二,因为今年毕业现在一直忙于面试,一家公司的笔试题上有这样一道题,请例举你所看过的有关程序设计的书,并写出你对最喜欢的那本书的读后感,我当时马上就写了这样一句话——我最喜欢的是《算法导论》,因为算法让我知道同样一个问题当处于不同环境和不同规模的时候它有不同的最优解。好了不扯了,直接进入正题。

        这是百度之星改版后第一场区域赛,因为当时忙于面试,忘了时间,等自己晚上回来打开电脑时,只剩下半个小时了,瞄了下题目,心里窃喜,这不是贪心吗,后来仔细一看确实是贪心,但是自己做的时候在分段上出问题了,因为赶时间便改用动态规划,写完后测试,小规模问题即题目上的例子没问题,但是在百度云IDE上挂了,后面没时间就没做出来,可能是超时吧!前几天有空去论坛上看了下题解,心中有点懊恼,应该相信自己的第一感觉,其实这个题目并不难,和我省赛的时候一样,当有时间限制的时候,大脑总是短路,一旦比赛完之后,又恢复正常了。题目如下。

平衡负载

Du熊正在负责一个大型的项目,目前有K台服务器,有N个任务需要用这K台服务器来完成,所以要把这些任务分成K个部分来完成,在同上台服务器上执行的任务必须是连续的任务,每个任务有各自需要的执行时间。

例如N=5,K=2,每个任务需要时间分别为5,3,1,4,7分钟,那么我们可以分成(5)(3 1 4 7)两部分,这样第一台服务器所花时间就是5分钟,而第二台机器需要花15分钟,当然,所有任务完成的时间是按最迟完成的那台服务器的时间,即这样划分的话完成所有任务所需要的时间就是15分钟。而另外一种划分方法是(5 3 1)(4 7),这种划分方案完成所有任务的时间就是11分钟,也是最优的一种划分方案。

现在你的任务就是根据给定的N,K和每个任务要花费的时间,找出使完成所有任务时间最短的方案。

输入:

多组输入。

第一行输入NK1<=K<=N<=10000)。

第二行输入N个不大于1000的正整数,表示各个任要花费的时间。

N=K=0表示输入结束。

输出:

每行输出一个整数,对应对于每个数据(除了N=K=0不用输出)。 

样例输入:

5 1

5 3 1 4 7

5 2

5 3 1 4 7

5 3

5 3 1 4 7

10 3

1 2 3 4 5 6 7 8 9 10

0 0

样例输出:

20

11

8

21

改了一下源代码,虽然不规范但是主要理解其中的核心算法就行了,代码如下。

#include<stdio.h>
#define Max 10000

/*
 * 这个函数是贪心分段,即如果以m值可以划分成K段或这更小则返回true否则返回false
 */
bool check( int a[], const int K, const int m,const int N)
{
    int sNum = 0, acc = 0;
    for(int i=0;i<N;i++) {
        if (a[i]> m) return false;
        acc += a[i];
        if (acc> m) {
            acc = a[i];
            sNum++;
        }
    }
    sNum++;
    return sNum <= K;
}
int main()
{
    int N, K,i;
    while (true) {
        scanf("%d%d",&N, &K);
        if (!N&& !K) break;
        int a[Max] ;
       for(i=0;i<N;i++)
		   scanf("%d",&a[i]);
        int l = 0,r = 0;
        for(i=0;i<N;i++)
			r += a[i];
		/*
		 *任务最短时间的大小l的区间为[r/K,r]。所以,以这个区间段的m值为分段标准进行分段,
		 *当分段成功则l为最小值退出循环。
		 */
        while (l <r) {
            int m = (l+ r) / 2;
            if(check(a, K, m,N))
                r = m;
            else l = m +1;
        }
		//因为两处都是最优解,所以总体为最优。
        printf("%d\n", l);
    }
    return 0;
}

你可能感兴趣的:(百度之星区域赛第一题——平衡负载题解)