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