剪草

【题目描述】
有N棵小草,编号0至N-1。奶牛Bessie不喜欢小草,所以Bessie要用剪刀剪草,目标是使得这N棵小草的高度总和不超过H。在第0时刻,第i棵小草的高度是h[i],接下来的每个整数时刻,会发生如下三个步骤:
(1)每棵小草都长高了,第i棵小草长高的高度是grow[i]。
(2)Bessie选择其中有一棵小草并把它剪平,这棵小草高度变为0。注意:这棵小草并没有死掉,它下一秒还会生长的。
(3)Bessie计算一下这N个小草的高度总和,如果不超过H,则完成任务,一切结束,否则轮到下一时刻。
你的任务是计算:最早是第几时刻,奶牛Bessie能完成它的任务?如果第0时刻就可以完成就输出0,如果永远不可能完成,输出-1,否则输出一个最早的完成时刻。
【输入格式】
第一行,两个整数N和H。 1 <= N <= 50,0 <= H <= 1000000。
第二行,N个整数,表示h[i]。0 <= h[i] <= 100000。
第三行,N个整数,表示grow[i]。1 <= grow[i] <= 100000。
【输出格式】
一个整数,最早完成时刻或-1。
【样例输入】
7 33
5 1 6 5 8 4 7
2 1 1 1 4 3 2
【样例输出】
5
【样例解释】
第1秒剪第2棵小草,第2秒剪第0棵小草,第3秒剪6棵小草,第4秒剪第5棵小草,第5秒剪第4棵小草。
【分析】
动态规划,设F[i,j]表示在前i棵草中割j刀的最优解。先以生长速度为关键字排序消除后效性,再用动态规划求解。

uses math;
var
  i,j,k,n,high:longint;
    h,g:array[-1..51]of longint;
    f:array[-1..51,-1..51]of longint;
procedure qsort(l,r:longint);
var
  i,j,temp,mid:longint;
begin
  i:=l; j:=r;
  mid:=g[(l+r) div 2];
  repeat
    while g[i]<mid do inc(i);
    while g[j]>mid do dec(j);
    if i<=j then
    begin
      temp:=g[i];g[i]:=g[j];g[j]:=temp;
            temp:=h[i];h[i]:=h[j];h[j]:=temp;
      inc(i);dec(j);
    end;
  until i>j;
  if l<j then qsort(l,j);
  if i<r then qsort(i,r);
end;
begin
  readln(n,high);
    if high=0 then begin write(-1);exit; end;
    for i:=1 to n do read(h[i]);
    for i:=1 to n do read(g[i]);
    qsort(1,n);
    for i:=0 to n do begin
      for j:=1 to n do f[j,0]:=f[j-1,0]+h[j]+g[j]*i;
        for j:=1 to n do
          for k:=1 to i do
              f[j,k]:=min(f[j-1,k-1]+g[j]*(i-k),f[j-1,k]+h[j]+g[j]*i);
        if f[n,i]<=high then begin write(i);exit; end;
    end;
    write(-1);
end.

转载于:https://www.cnblogs.com/JRX2015U43/p/6533550.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值