HDU 1158 动态规划

#include "stdio.h"
#include "string.h"
#include "math.h"

#define MAX(a, b) ((a)>(b)?(a):(b))
#define MIN(a, b) ((a)<(b)?(a):(b))

int n;
int h, c, f;
int w[13];  //12个月

int main(){
	int i, j, z, m, min, k;
	int dp[13][200]; //dp[i][j],第i个月,保留j个工人时,花费总额。可以换成滚动数组节省空间。
	freopen("in.txt", "r", stdin);
	while(scanf("%d", &n), n){
		scanf("%d %d %d", &h, &c, &f);
		for(i=1; i<=n; i++) scanf("%d", w+i);
		memset(dp[0], 0, sizeof(dp[0]));
		w[0] = 0; //第0个月,工人数为0
		m = 0; //m,保存过去的月份中,最多的人数
		for(i=1; i<=n; i++){
			k = MAX(w[i], m);  //看当前月份人数,是否大于以前最多的人数
			for(j=0; j<=k; j++){
				//第i个月份,保留j名工人
				dp[i][j] = 0x7FFFFFFF;
				for(z=w[i-1]; z<=m; z++){  //z要从w[i-1]开始,即,首先得满足上个月人数要求
					//当j大于z时,需要再招人;当j小于等于z时,需要解雇人
					dp[i][j] = MIN(dp[i][j], dp[i-1][z] + abs(j-z)*((j>z)?h:f) + j*c);
				}
			}
			m = k;  
		}
		min = 0x7FFFFFFF;
		for(i=w[n]; i<=m; i++)
			min = MIN(dp[n][i], min);
		printf("%d\n", min);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值