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;
}

 

posted on 2010-06-13 21:06  ylfdrib  阅读(953)  评论(1编辑  收藏  举报