Employment Planning
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5190 Accepted Submission(s): 2225
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
题意:一个工程需要进行m个月,每个月需要Ni个人,可以是第一个月招的人继续干,或者是这个月炒掉几个上个月的工人来节约工资,或者多招几个人。每次招一个人花费hire元,炒一个人花费fire元,每个人一个月工资为salary,问你m个月你需要的花费最少是多少?
思路:简单DP,dp[ i ][ j ]表示第 i 个月雇佣着 j 个人。但是这个SB题没有给出数据范围,我默认每个月不会超过1500个人AC了,而且这个题最烦的地方是他的数据里面有该月工程需要0个人。。。
状态转移方程:if(j == k)dp[i][j] = min(dp[i-1][k] + s*j,dp[i][j]);
else if(j < k)dp[i][j] = min(dp[i-1][k] + s*j + (k-j)*f,dp[i][j]);
else if(j > k)dp[i][j] = min(dp[i-1][k] + s*j + (j-k)*h,dp[i][j]);
else if(j < k)dp[i][j] = min(dp[i-1][k] + s*j + (k-j)*f,dp[i][j]);
else if(j > k)dp[i][j] = min(dp[i-1][k] + s*j + (j-k)*h,dp[i][j]);
#include<bits/stdc++.h>
#define INF 0xfffffff
using namespace std;
int dp[15][1505];
int need[15];
int main(){
int month;
int h,s,f;
while(scanf("%d",&month) && month){
scanf("%d%d%d",&h,&s,&f);//!!input hire salary fire
int maxneed = 0;
for(int i =1 ; i <= month; i++){ //!!input
scanf("%d",&need[i]);
maxneed = max(maxneed,need[i]);
}
for(int i = 0; i <= month; i++)//!!初始化
for(int j = 0; j <= maxneed; j++)
dp[i][j] = INF;
for(int i = need[1]; i <= maxneed; i++)//!!初始化
dp[1][i] = i*(h+s);
for(int i = 2; i <= month; i++)//!!状态转移
for(int j = need[i]; j <= maxneed; j++){
for(int k = need[i-1]; k <= maxneed; k++){
if(j == k)dp[i][j] = min(dp[i-1][k] + s*j,dp[i][j]);
else if(j < k)dp[i][j] = min(dp[i-1][k] + s*j + (k-j)*f,dp[i][j]);
else if(j > k)dp[i][j] = min(dp[i-1][k] + s*j + (j-k)*h,dp[i][j]);
}
}
int minn = INF;
for(int i = 1; i<= maxneed; i++){
minn = min(minn,dp[month][i]);
}
cout << minn <<endl;
}
}