hdu 1158 Employment Planning (dp)

小记:这题的转移方程 需要动脑,奈何想不到,就做不到。我还是看了一下别人的dp[i][j] 的意思,然后转移方程自己写出来了。 唉,dp就是定义和转移方程难想。无后效性,和最优解,这两个必须满足,才能动用dp。


思路:dp,每个dp的转移方程若是不是自己想出来的,那么这道题,个人觉得收获已经不会大了。

dp[i][j] 表示前i个月,在第i个月的时候有j人的最小花费。

转移方程:dp[i][j] = min(dp[i-1][k] + cost, dp[i][j])  ( k >= person[i-1] && k <= personMax) 

 if(j => k)   cost = (j - k) * hire + j * salary;

if(j <= k )   cost = (k - j) * fire + j * salary;

person[i] 是第i个月 需要的人数,personMax是 max(person[i]) (i >= 1 && i <= n)

初始化第一个月的值即可。

dp[1][i] = i * (hire + salary); (i >= person[1] && i <= personMax)


最后的answer = min(dp[n][i]) (i >= person[n] && i <= personMax)


代码:

#include <stdio.h>
#include <string.h>
#include <stack>
#include <iostream>
#include <map>
#include <set>
#include <algorithm>
using namespace std;

#define mst(a,b) memset(a,b,sizeof(a))

const int MAX_ = 15;
const int MAX = 0x7fffffff;

int person[MAX_];
int dp[MAX_][MAX_*100];

int main() {
    int T;
    int m, k, n, hire, salary, fire, personMax;

    while(scanf("%d",&n),n){
        personMax = -1;
        scanf("%d%d%d",&hire,&salary,&fire);

        for(int i = 1; i <= n; ++i){
            scanf("%d",&person[i]);
            personMax = max(personMax,person[i]);
        }

        for(int i = person[1]; i <= personMax; ++i){
        	dp[1][i] = i * (hire + salary);
        }

        for(int i = 2; i <= n; ++i){
        	for(int j = person[i]; j <= personMax; ++j){
                int minm = MAX;
                for(int k = person[i-1]; k <= personMax; ++k){
                    int cost;
                    if(j > k){
                        cost = (j - k) * hire + j * salary;
                    }
                    else {
                        cost = (k - j) * fire + j * salary;
                    }
                    minm = min(minm,dp[i-1][k] + cost);
                }
                dp[i][j] = minm;
        	}
        }
        int ans = MAX;
        for(int i = person[n]; i <= personMax; ++i){
            ans = min(ans,dp[n][i]);
        }
        printf("%d\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值