由于题目中未说明工人人数的数据范围,于是用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);
}
}