题目大意:给定月数n,给定雇佣一个人的花费hi,每个人一个月的工资sa和开除一个人的花费fi。再给定每个月需要的最少人数num[i]。求每月怎样安排雇佣和开除人,使得n个月的花费最少
maxn = max(num[i]);
dp[i][j]:第i月雇j个人的花费
初始化:dp[1][i] = i*(hi+fa);
状态转移:
(1)如果该月雇佣的人数j>=上月雇佣的人数k:dp[i][j]=min(dp[i][j],dp[i-1][k]+j*sa+(j-k)*hi);
(2)反之:dp[i][j]=min(dp[i][j],dp[i-1][k]+j*sa+(k-j)*fi);
最后ans = min(dp[n][i]);(num[n]<=i<=maxn);
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 999999999;
const int N = 15;
const int M = 1010;
int dp[N][M];//第i个月雇j个人的花费
int num[N];//人数
int hi, sa, fi;
int n;
int main()
{//可以多雇人,使费用降低,雇人上限maxn
while(~scanf("%d", &n) && n)
{
scanf("%d %d %d", &hi, &sa, &fi);
int maxn = -INF;
for(int i = 1; i <= n; ++i)
{
scanf("%d", &num[i]);
maxn = max(maxn, num[i]);
}
memset(dp, 0x3f, sizeof(dp));//求最小值,将dp初始化为无穷大
for(int i = 1; i <= maxn; ++i)
dp[1][i] = i*(hi+sa);
for(int i = 2; i <= n; ++i)
for(int j = num[i]; j <= maxn; ++j) //该月的状态
for(int k = num[i-1]; k <= maxn; ++k)//由上月转移而来
if(j>=k) dp[i][j] = min(dp[i][j], dp[i-1][k]+j*sa+(j-k)*hi);
else dp[i][j] = min(dp[i][j], dp[i-1][k]+j*sa+(k-j)*fi);
int ans = INF;
for(int i = num[n]; i <= maxn; ++i)
ans = min(ans, dp[n][i]);
printf("%d\n", ans);
}
return 0;
}