http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3778
题目
某人做菜很厉害,一分钟能同时完成最多m个菜的一道工序,输入菜的个数n和整数m,再输入每个菜的工序数,输出最短时间。
范围:
1 <= N, M <= 40000
1 <= Ai <= 40000
Sample Input
2 3 2 2 2 2 10 6 1 2 3 4 5 6 7 8 9 10
Sample Output
3 10
题解
贪心,策略是每次选择剩余工序最多的m个菜,选其他的结果肯定不会变好,时间复杂度$mathcal{O}(n^2log n)$绝对超时
比如:
发现可以把这张图分成两部分,就是足够一次完成m道工序的情况和不能一次完成m道工序的情况,能一次完成m道工序很简单,直接除法就好了,剩下不能一次完成m道工序的部分
这个只是中间状态,还有能完成m道工序的部分
一直到下面这种情况
然后就发现经过的时间就等于蓝色部分的高度(只算一道菜……),因为总是从蓝色部分开始往右选择工序
设答案为和除以m
有一个问题,就是如果不能整除怎么办,为什么不能整除
不能整除说明存在黄色部分,需要加这部分高度,即答案+1
剩下黄色部分就是不能一次完成m道工序的部分(按行),因此答案是蓝色部分高度加黄色部分的高度,因为黄色部分除以m肯定小于黄色部分的高度,因此和除以m一定小于最高高度,所以这个时候可以直接让答案为最高高度
AC代码
#include<cstdio> #include<cstring> #include<cmath> #define REP(r,x,y) for(register int r=(x); r<(y); r++) #define REPE(r,x,y) for(register int r=(x); r<=(y); r++) #define PERE(r,x,y) for(register int r=(x); r>=(y); r--) #ifdef sahdsg #define DBG(...) printf(__VA_ARGS__), fflush(stdout) #else #define DBG(...) (void)0 #endif // sahdsg using namespace std; typedef long long LL; inline int max(int a, int b) { return a>b?a:b; } #define MAXN 30000007 typedef long long LL; int main() { int t; scanf("%d", &t); while(0<t--) { int n,m; scanf("%d%d", &n, &m); int maxx=-1; LL sum=0; REP(i,0,n) { int k; scanf("%d", &k); maxx = max(maxx,k); sum+=k; } LL ans=sum/m; if(sum%m) ans++; if(ans<maxx) ans=maxx; printf("%lld ", ans); } }