剪草
题目大意:
有n棵小草,B某看它们很不顺眼,想让他们的高度总和不大于H,它们一开始各有一个高度,然后它们各有一个固定的生长值,B某每个单位时间可以将一棵草减掉(让他的高度变为0),但小草每个单位时间会长一次,问B某在哪个时间可以让小草总高度不大于H,如果永远不可能,那就输出-1
数据范围限制
1 ≤ N ≤ 50,0 ≤ H ≤ 1000000
0 ≤ h[i] ≤ 100000
1 ≤ grow[i] ≤ 100000
对于20%的数据, 1 ≤ N ≤ 7。
提示
解题思路:
我们可以用f[i][j]来表示前i棵草减j次的最小高度,然后先枚举结束时间(k),再枚举第几棵小草(i),再枚举当前时间(j),就得出下图的公式,再套进去算一下就可以了
f[i][j]=min{f[i−1][j]+a[i].g+a[i].grow∗k不选f[i−1][j−1]+a[i].grow∗(k−j)选f[i][j]=min\left\{\begin{matrix}f[i-1][j]+a[i].g+a[i].grow*k &不选\\ f[i-1][j-1]+a[i].grow*(k-j)&选\end{matrix}\right.f[i][j]=min{f[i−1][j]+a[i].g+a[i].grow∗kf[i−1][j−1]+a[i].grow∗(k−j)不选选
注释:
不选的话就要加上他的高度,再生长k次,选的话就不加高度,但要算出接下来要生长的高度(k-j)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int ans,n,h,f[55][55];
struct rec
{int grow,g;
}a[55];
bool cmp(rec x,rec y)
{return x.grow<y.grow;
}
int main()
{ans=-1;scanf("%d %d",&n,&h);for (int i=1;i<=n;++i)scanf("%d",&a[i].g);for (int i=1;i<=n;++i)scanf("%d",&a[i].grow);sort(a+1,a+1+n,cmp);for (int k=0;k<=n;++k){for (int i=1;i<=n;++i)for (int j=1;j<=i;++j)f[i][j]=2147483647;for (int i=1;i<=n;++i) f[i][0]=f[i-1][0]+a[i].g+a[i].grow*k;for (int i=1;i<=n;++i)for (int j=1;j<=k;++j)f[i][j]=min(f[i-1][j]+a[i].g+a[i].grow*k,f[i-1][j-1]+a[i].grow*(k-j));if (f[n][k]<=h){ans=k;break;}}printf("%d",ans);return 0;
}