Employment Planning

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


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


解题思路:本题为动态规划题目,每个月处理的人数都应该是以本月需要的人数为下限,以这个工期需要人数最多的月份的人数为上限。也许上个月需要的人数很多,本月需要人数很少,下个月需要的人数又很多,这样就要考虑到招聘费和解雇费。所以,在处理人数时,每个月不是处理一个,而是处理一批。处理时应该是:第i个月聘用j个人(j=emp[i];j<=max1;j++);
状态转移方程:pay[i][j]=pay[i][j]<temp?pay[i][j]:temp;其中temp=pay[i-1][k]+j*work+(招聘或解雇所需费用)



#include<stdio.h> #include<algorithm> using namespace std; int main() {     int emp[13];   //存储每个月需要的人数     int pay[13][1010];    //pay[i][j]存储第i个月雇佣j个人的最小费用      int max1;    //所有工期内需要雇佣的最大人数     int hir,work,fir;    //招聘一个人、雇佣一个人、解雇一个人需要花的钱     int temp;     int n,i,j,k;     while(scanf("%d",&n)&&n)     {         scanf("%d%d%d",&hir,&work,&fir);         max1=0;         for(i=1;i<=n;i++)         {             scanf("%d",&emp[i]);             max1=max1>emp[i]?max1:emp[i];  //寻找最大人数         }         for(i=0;i<=n;i++)   //边界数据初始化为最小值             pay[i][0]=0;         for(i=0;i<=max1;i++)   //最开始雇佣的人都需要招聘费             pay[0][i]=i*hir;         emp[0]=0;         for(i=1;i<=n;i++)         {             for(j=emp[i];j<=max1;j++)  //第i个月聘用j个工人所需的最低花费             {                 pay[i][j]=0xfffffff;  //需处理值初始化化为最大值                 for(k=emp[i-1];k<=max1;k++)   //对于第i个月聘用j个工人所需的最低花费,检索上个月所有可能雇佣的人数花费信息,取最小值                 {                     temp=pay[i-1][k]+j*work;   //前面所有的花费加上这个月需要雇佣人的花费                     if(k>j)   //检查相对于上个月的人数是招聘了人还是解雇了人,计算费用                         temp+=(k-j)*fir;                      else if(k<j)                         temp+=(j-k)*hir;                     pay[i][j]=pay[i][j]<temp?pay[i][j]:temp;     //检索上个月所有可能雇佣的人数花费信息,取最小值                 }             }         }         sort(pay[n]+emp[n],pay[n]+max1+1);   //对最后一个月的花费排序,找出最小值         printf("%d\n",pay[n][emp[n]]);     }     return 0; }