公司每个月都需要一定量的人,雇佣和解雇人都需要钱,但每月人数都在变化,让他放着不干活给工资不一定比再雇一个画的前多,求最小花费。
由于当前子问题需要建立在上一个最有子问题的基础上,所以需要DP。题意不好理解。
dp[i][j]表示前i个月(包含本月)总人数为j的最小花费,从上往下DP。
状态方程:相比上一月人数增多,dp[i][j] = dp[i - 1][k] + (j - k) * hir + sal * j;
相比上一月人数减少,dp[i][j] = dp[i - 1][k] + (j - k) * fir + sal * j;
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 1005;
const int INF = 1000000;
int n, dp[15][N], need[15];
int main()
{
// freopen("in.txt", "r", stdin);
int i, j, k, hir, fir, sal, maxn, ans, temp;
while(~scanf("%d", &n) && n)
{
maxn = 0;
scanf("%d%d%d", &hir, &sal, &fir);
for(i = 1; i <= n; i ++)
{
scanf("%d", &need[i]);
maxn = max(maxn, need[i]);
}
memset(dp, 0, sizeof(dp));
for(i = need[1]; i <= maxn; i ++)
dp[1][i] = (hir + sal) * i;
for(i = 2; i <= n; i ++)
for(j = need[i]; j <= maxn; j ++)
{
int minn = INF;
for(k = need[i - 1]; k <= maxn; k ++)
{
if(j >= k)
{
temp = dp[i - 1][k] + (j - k) * hir + j * sal;
}
else
{
temp = dp[i - 1][k] + (k - j) * fir + j * sal;
}
minn = min(minn, temp);
}
dp[i][j] = minn;
}
ans = INF;
for(i = need[n]; i <= maxn; i ++)
ans = min(ans, dp[n][i]);
printf("%d\n", ans);
}
return 0;
}