jzoj P1510【普及模拟】剪草

127 篇文章 0 订阅
71 篇文章 0 订阅

题目描述

有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。

对于20%的数据, 1 ≤ N ≤ 7。

输出

一个整数,最早完成时刻或-1。
题解:
排序+DP:
f[i,j]表第示前i颗草减j次的最小高度值。
2.多次割同一颗草,只有最后一次有效,因为它可以再次生长,所以每个草最多被割一次,答案其实就是最少要减多少次,而次数不超过n(草的数量)。
3.先割生长速度慢的明显比先割生长速度快的要优,所以从小到大排序生长速度。
4.做DP。
f[j,k]:=min(f[j-1,k]+a[j]+b[j] * i,f[j-1,k-1]+h[j] *(i-k));
f[j-1,k]+a[j]+b[j] * i 表示不割第j颗草时,前j-1颗草k个时刻的最小高度值加上他的高度跟他在i时刻内生长的高度h[j] * i。
f[j-1,k-1]+h[j] * (i-k)表示割j颗草的时候,前j-1颗草减k-1次的最小高度值加上他生长时间(i-k)*他生长速度h[j]的值(他在第k个时刻被割)

var
   f:Array [0..51,0..51] of longint;
   a,h:array [0..51] of longint;
   i,j,k,n,m:longint;

function min(x,y:longint):longint;
begin
   if x<y then exit(x);
   exit(y);
end;

begin
     readln(n,m);
     for i:=1 to n do read(a[i]); readln;
     for i:=1 to n do read(h[i]);
     for i:=1 to n-1 do
         for j:=i+1 to n do
             if h[i]>h[j] then
                begin
                    a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
                    h[0]:=h[i];h[i]:=h[j];h[j]:=h[0];
                end;
         for i:=0 to n do
             begin
                  for j:=1 to n do
                      for k:=1 to i do f[j,k]:=maxlongint div 3;
                  for j:=1 to n do f[j,0]:=f[j-1,0]+a[j]+h[j]*i;
                  for j:=1 to n do
                      for k:=1 to i do
                          f[j,k]:=min(f[j-1,k]+a[j]+h[j]*i,f[j-1,k-1]+h[j]*(i-k));
                  if f[n,i]<=m then
                     begin
                         writeln(i);
                         halt;
                     end;
             end;
     writeln('-1');
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值