HDU1158 Employment Planning(DP)

题目:

Employment Planning

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5314    Accepted Submission(s): 2275


Problem Description
A project manager wants to determine the number of the workers needed in every month. He does know the minimal number of the workers needed in each month. When he hires or fires a worker, there will be some extra cost. Once a worker is hired, he will get the salary even if he is not working. The manager knows the costs of hiring a worker, firing a worker, and the salary of a worker. Then the manager will confront such a problem: how many workers he will hire or fire each month in order to keep the lowest total cost of the project. 
 

Input
The input may contain several data sets. Each data set contains three lines. First line contains the months of the project planed to use which is no more than 12. The second line contains the cost of hiring a worker, the amount of the salary, the cost of firing a worker. The third line contains several numbers, which represent the minimal number of the workers needed each month. The input is terminated by line containing a single '0'.
 

Output
The output contains one line. The minimal total cost of the project.
 

Sample Input
  
  
3 4 5 6 10 9 11 0
 

Sample Output
  
  
199
 

Source
 

Recommend
Ignatius   |   We have carefully selected several similar problems for you:   1227  1074  1080  1024  1078 
 

Statistic |  Submit |  Discuss |  Note
思路:

有一家公司要完成一个课题,该课题分为n个月完成。现在知道每个月至少需要多少人手才能完成这个阶段的任务。假如说我们要聘请一个员工,那么我们就要有一定的花费(第二行的第一个数字);假如说我们解雇一个员工,那么我们也有一定的花费(第二行的第三个数字)。当然员工也是要拿工资的,每个月拿一定量的工资(假如说某个员工不干活也是拿工资的,第二行第二个数字),问你完成这个课题,最小需要花费多少钱?
样例解释:
3  //一个课题分三个月解决
4 5 6  //分别为聘请一个员工的花费、一个员工的工资、一个员工被解雇的花费
10 9 11 //第一个月至少需要10个人,第二个月至少需要9个人,第三个月至少需要11个人
输出:
199
第一个月聘请10个员工,花费:10*4+10*5(工资+聘请的费用)=90
第二个月不聘请员工(当然我们也可以解雇一个员工,当然也可以完成该阶段的任务,但是不聘请员工的做法才能达到最优解,具体你可以自己再纸上算算),花费:10*5=50(工资)
第三个月聘请一个员工,花费:10*5+4+5=59(10个人的工资+新聘请员工的工资+招聘费用)
那么总花费就是:90+50+59=199 即为最优解。

我们可以聘请任意个员工,也可以解雇任意个员工,当然也可以不解雇员工。所以我们定义:dp[i][j]表示对于第i个阶段,保留j个人(要完成当月的任务)所需要的最少花费。但是我们怎么知道最多会有几个人会被保留呢?其实结果就是每个月需要聘请员工的最大值。

代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int dp[20][1000];//表示第几个月保留几个人所需的最小花费
int num[20];//当前月份需要几个人
int main()
{
    int n;
    while(scanf("%d",&n)&&n)
    {
        int a,b,c,maxx=0;//a,b,c分别表示聘请的的花费、每月的工资花费、开除一个人的花费
        scanf("%d%d%d",&a,&b,&c);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&num[i]);
            maxx=max(maxx,num[i]);//找出人数的最大需求量
        }
        mem(dp,1);//注意这时候把dp初始化任意一个正值就行,这个正值虽然随机但是比1大
        for(int i=num[1]; i<=maxx; i++)
            dp[1][i]=a*i+b*i;//初始化第一个月保留的人数的月花费
        for(int i=2; i<=n; i++)
            for(int j=num[i]; j<=maxx; j++)
                for(int k=0; k<=maxx; k++)
                    if(k<=j)//表示当前状态是由聘请了(j-k)个人得来的
                        dp[i][j]=min(dp[i][j],dp[i-1][k]+(j-k)*a+j*b);
                    else//表示当前状态是由解雇了(k-j)个人得来的
                        dp[i][j]=min(dp[i][j],dp[i-1][k]+(k-j)*c+j*b);
        int ans=9999999;
        for(int i=0; i<=maxx; i++)
            ans=min(dp[n][i],ans);
        printf("%d\n",ans);//寻找最小值
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值