ZOJ 3778 Talented Chef

来源:互联网 发布:java主方法怎么写 编辑:程序博客网 时间:2024/05/17 06:06

问题转化一下,就是给定n堆石子,每次最多可以选m堆,每堆里只能取走一个石子,问最快几次取完。

最多的一堆棋子的个数为t,石子总个数为sum。

若t*m>=sum,

这时,t-1次内是不能取完所有石子的,故至少需要t次,下面是一种t次取完的做法。

画一个t*m的棋盘(t行m列),把a1从第1列最下角开始,一个一个从下向上地放进第一列,第一个石子放在(t,1),第2个放在

(t-1,1)...然后放a2,a3....当i列放慢,就从(t,i+1)开始从下向上放。

这样,这个棋盘足够容纳所有石子。对任意一堆石子ai,其中的石子要么全在一列,要么在2个相邻的列,列i,列i+1,

同时,因为ai<=t,故ai中的任意2个石子不在同一行。

然后,我们每次取走一行,就能用t步取完。

若t*m<sum,此时令f=sum/m+(sum%m?1:0);

由于(f-1)*m<sum,f*m>=sum

故f-1次内不能取完,而我们可以用f次取完。

首先f>t



#include <iostream>

#include <stdio.h>
#include <string.h>


using namespace std;


int main()
{
    int t,n,m,x;
    scanf("%d",&t);
    while(t--)
    {
        int maxn = 0;
        int sum = 0;
        int ans = 0;
        scanf("%d %d",&n, &m);
        for(int i= 0; i<n; i++)
        {
            scanf("%d",&x);
            sum += x;
            if(maxn < x)
             maxn  = x;
        }


      if( sum % m == 0)
       ans = sum/m;
    else if( sum % m != 0)
       ans = sum/m + 1;
    if( maxn > ans )
     printf("%d\n",maxn);
    else
     printf("%d\n",ans);


  }


}
0 0