hdu Employment Planning (dp)

由于题目中未说明工人人数的数据范围,于是用dp先尝试了一下;

dp[i][j]表示前i个月(包括i)请j个人所花费的最少费用;

那么动态转移方程为:

当k<=j时

dp[i][j]=min(dp[i-1][k]+(j-k)*h+j*s,dp[i][j]);

当k>j时

dp[i][j]=min(dp[i-1][k]+(k-j)*f+j*s,dp[i][j]);

其中h为雇佣工人的花费,s为工人的月工资,f为解雇工人的花费;

值得注意的是若人数范围大于1000,可能会超时,应该用贪心的思想去解。

#include <stdio.h>
#include <string.h>
#define maxn 1005
#define inf 99999999
int Max;
int h,s,f;
int mon;
int H[13];
int dp[13][maxn];
void solve()
{
	int i,j,k;
	memset(dp,-1,sizeof(dp));
	dp[1][H[1]]=H[1]*h+s*H[1];
	for(i=2;i<=mon;i++)
		for(j=H[i];j<=Max;j++)
			for(k=H[i-1];k<=Max;k++)
			if(dp[i-1][k]!=-1)
			{
				if(k<=j)
				{
					if(dp[i][j]==-1 || dp[i][j]>dp[i-1][k]+j*s+(j-k)*h)
						dp[i][j]=dp[i-1][k]+j*s+(j-k)*h;	
				}
				else
				{
					if(dp[i][j]==-1 || dp[i][j]>dp[i-1][k]+j*s+(k-j)*f)	
						dp[i][j]=dp[i-1][k]+j*s+(k-j)*f;
				}
			}	
}
int main()
{
	int i,ans;
	while(scanf("%d",&mon),mon)
	{
		scanf("%d%d%d",&h,&s,&f);
		Max=-1;
		for(i=1;i<=mon;i++)	
		{
			scanf("%d",&H[i]);
			if(Max<H[i])
				Max=H[i];
		}
		solve();
		ans=inf;
		for(i=H[mon];i<=Max;i++)
			if(dp[mon][i]<ans)
				ans=dp[mon][i];
		printf("%d\n",ans);
		
	}	
}



你可能感兴趣的:(hdu Employment Planning (dp))