题意
思路
我们先按照生长的速度排序,剪最慢的肯定是比剪最快的好,因为剪了最快的它之后又会以很快的速度增加长度,因此我们从最慢的开始剪。设f[j][k]为前j棵草剪k次的最小值,我们可以得出动态转移方程:
f[j][k]=min(f[j−1][k]+c[j].h+c[j].g∗i,f[j−1][k−1]+c[j].g∗(i−k))f[j][k]=min(f[j−1][k]+c[j].h+c[j].g∗i,f[j−1][k−1]+c[j].g∗(i−k))
其中f[j-1][k]+c[j].h+c[j].g*i为不割掉当前的草,所以我们要加上它的初始高度和之后会长到的高度;
f[j-1][k-1]+c[j].g*(i-k)为割掉当前的草,所以我们要加上它剩下(i-k)次的生长次数。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,f[51][51];
struct node{
int g,h;
}c[51];
int cmp(node x,node y){return x.g<y.g;}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&c[i].h);
for (int i=1;i<=n;i++)
scanf("%d",&c[i].g);
sort(c,c+n+1,cmp);//按照生长速度排序
for (int i=0;i<=n;i++)//枚举割草的次数
{
for (int j=1;j<=n;j++)
{
f[j][0]=f[j-1][0]+c[j].h+c[j].g*i;//初始化
for (int k=1;k<=i;k++)
f[j][k]=2147483647;
}
for (int j=1;j<=n;j++)
for (int k=1;k<=i;k++)
f[j][k]=min(f[j-1][k]+c[j].h+c[j].g*i,f[j-1][k-1]+c[j].g*(i-k));
if (f[n][i]<=m)
{
printf("%d",i);//如果满足条件就可以直接输出退出了
return 0;
}
}
printf("-1");
}