http://acm.hdu.edu.cn/showproblem.php?pid=1158
题目大意:一个项目经理准备招一部分工人做事,每个月所需要的工人人数不一样,经理可以看情况hires or fires a worker,雇人或解雇都需要钱,雇的人不干活也需要发工资,要求怎样安排才能使得完成整个工作花费最少
算法分析:简单dp,以第i个月结束时,现有j个人的最小花费dp[i][j]为状态量,对人数进行枚举,状态转移方程为dp[i][j] = MAX(dp[i-1][k] + cost, g[i-1] <= k <= maxN),其中cost为从状态dp[i-1][k]转移到dp[i][j]所需额外花费,g[i]表示第i个月所需最少的工人数,maxN表示所有月所需最大的工人数
代码
#include<stdio.h>
#include<string.h>
#define NN 15
#define INF 0xfffffff
int n, hire, sala, fire, maxN;
int g[NN];
int dp[NN][1000];
void solve()
{
int i, j, k, min, tmp;
for (i = g[1]; i <= maxN; i++)
dp[1][i] = (hire + sala) * i;
for (i = 2; i <= n; i++){
for (j = g[i]; j <= maxN; j++){
min = INF;
for (k = g[i - 1]; k <= maxN; k++){
if (k > j){
tmp = dp[i - 1][k] + fire * (k - j) + sala * j;
}else
tmp = dp[i - 1][k] + hire * (j - k) + sala * j;
if (tmp < min)
min = tmp;
}
dp[i][j] = min;
}
}
min = INF;
for (i = g[n]; i <= maxN; i++)
if (dp[n][i] < min)
min = dp[n][i];
printf("%d\n", min);
}
int main()
{
int i;
while (scanf("%d", &n) != EOF){
if (n == 0) break;
scanf("%d%d%d", &hire, &sala, &fire);
maxN = 0;
for (i = 1; i <= n; i++)
{
scanf("%d", &g[i]);
if (g[i] > maxN)
maxN = g[i];
}
solve();
}
return 0;
}