目录:
题目:
题意:
有个穷b,他买不起除草机,只能用剪刀来剪,现在问我们,他最早在什么时候可以达成所有草的总高度<=要求高度
分析:
动态规划是正解,不过不算纯正的动归,有贪心的成分
因为长得快的草如果先剪,那很快就会长高,如果先剪长得慢的草,那高度就增长慢一些,所以应先割长得慢的草。如果剪了n次还没有达到目标,那么永远也不会达到目标。
所以先将生长速度排序,然后动归
f[j,k]表示前j棵草剪了k次的总最小高度
f[j,0]要预处理
对于每棵草和每次剪草,可以考虑剪这棵草和不剪这棵草。剪则总高度=
f[j−1,k−1]+g[i]∗(i−k)
f
[
j
−
1
,
k
−
1
]
+
g
[
i
]
∗
(
i
−
k
)
,不剪则=
f[j−1,k]+a[i]+g[i]∗i
f
[
j
−
1
,
k
]
+
a
[
i
]
+
g
[
i
]
∗
i
还有最后别忘了输出-1
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
struct node{
int g,grow;
}x[51];
int f[51][51];
bool cmp(node a,node b)
{
return a.grow<b.grow;
}
int min(int a,int b)
{
return a<b? a:b;
}
int main()
{
/* freopen("grass.in","r",stdin);
freopen("grass.out","w",stdout);*/
int n=read(),h=read();
for(int i=1;i<=n;i++) x[i].g=read();
for(int i=1;i<=n;i++) x[i].grow=read();
sort(x+1,x+1+n,cmp);
for(int i=0;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
f[j][0]=f[j-1][0]+x[j].g+x[j].grow*i;
for(int k=1;k<=i;k++)
f[j][k]=99999999;
}
for(int j=1;j<=n;j++)
for(int k=1;k<=i;k++)
f[j][k]=min(f[j-1][k]+x[j].g+x[j].grow*i,f[j-1][k-1]+x[j].grow*(i-k));
if(f[n][i]<=h) {printf("%d",i);return 0;}
}
printf("-1");
fclose(stdin);
fclose(stdout);
return 0;
}