【JZOJ】【DP】剪草

n n 棵草,第 i i 棵草的高度为 w h [ i ] . w wh[i].w ,在每一轮中,草都会长高 w h [ i ] . h wh[i].h ,有一个人来剪草,当他减掉某棵草时,他的高度就变为 0 0 ,你的任务是,用最短的时间使得所有的草高度总和不超过 m m ,如果不能则输出 1 -1

输入

输入样例#1
3 16
5 8 58
2 1 1
输入样例#2
2 58
5 8
2 1
输入样例#3
2 0
5 8
5 1

输出

输出样例#1
1
输出样例#2
0
输出样例#3
-1

思路

D P DP
f [ i ] [ j ] f[i][j] 代表前 i i 棵草,减 j j 次,最少的高度

#include<algorithm> 
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
struct whw
{
	int w,h;
}wh[2025];
int f[2005][2005];
int n,m,k,sum;
bool Nwh(whw i,whw j)
{return i.h<j.h;}
int main()
{
	freopen("grass.in","r",stdin);
	freopen("grass.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		scanf("%d",&wh[i].w);
	for(int i=1;i<=n;++i)
		scanf("%d",&wh[i].h);
	sort(wh+1,wh+n+1,Nwh);
	for(int i=0;i<=n;++i)
	{
		for(int j=1;j<=n;++j)
			for(int k=1;k<=i;++k)
				f[j][k]=1e9;
		for(int j=1;j<=n;++j)f[j][0]=f[j-1][0]+wh[j].w+wh[j].h*i;//赋初值(不剪)
		for(int j=1;j<=n;++j)
			for(int k=1;k<=i;++k)
				f[j][k]=min(f[j-1][k]+wh[j].w+wh[j].h*i,f[j-1][k-1]+wh[j].h*(i-k));//从剪与不剪中选取最大的
		if(f[n][i]<=m){printf("%d",i);return 0;}
	}
	printf("-1");
	fclose(stdin);
	fclose(stdout);
}

猜你喜欢

转载自blog.csdn.net/SSL_wujiajie/article/details/86685084