Employment Planning (HDU 1158)

来源:互联网 发布:工业机器人编程语言co 编辑:程序博客网 时间:2024/05/21 12:47

Employment Planning

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


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 610 9 110

Sample Output
199

Source
Asia 1997, Shanghai (Mainland China)

 

题意:

题意:给你一个n,然后给你3个数,分别代表雇佣费,薪水,解雇费,然后给你n个月的每月最低需要的人数,求最少花费费用。
刚开始我用贪心写的,但我以为自己写的是DP,结果WA。我非常不爽啊,怎么就不行呢,每次求出最小值后就能求最大值啊。。ca,纠结了一天。。后来发现我的思想是贪心啊!!靠。然后就不会写了==。看见别人都是用二维DP写的,我就想不通了,为什么一定要用二维的呢?反正MD就是不会写。于是看过n个人的文章后终有所悟,然后就水过了哭
 
思想:用一个二维的dp[i][j],i代表第几个月,j代表这个月所需人数,d[i][j]代表第i个月有j个人时从开始到现在共产生的最低费用。枚举每个月可能的雇佣人数,最小为num[i],最大为maxn(所有月份中最低所需人数的最大值)。于是本月与上个月就有两种关系(本月人数多的情况和少的情况),利用这种关系动态规划求出最小值(DP就是要这种重复的前后关系来进行递推)。第一个月直接是枚举可能性求出所需费用。
#include<cstdio>#include<algorithm>using namespace std;const int INF = 1<<30;int main(){    int n, i, j, k, hire, salary, fire, num[13], dp[13][105];    while(~scanf("%d", &n), n)    {        scanf("%d%d%d", &hire,&salary,&fire);        int maxn = 0;        for(i=1; i<=n; i++)        {            scanf("%d", num+i);            if(num[i] > maxn) maxn = num[i]; //求出最大需要人数        }        for(i=num[1]; i<=maxn; i++)            dp[1][i] = (hire+salary)*i; //1月所需人数到最大人数这几种情况所需花费        for(i=2; i<=n; i++)        {            for(j=num[i]; j<=maxn; j++)            {                int minn = INF;                for(k=num[i-1]; k<=maxn; k++)                {                    if(j >= k) minn = min(minn, dp[i-1][k]+(j-k)*hire+j*salary);                    else  minn = min(minn, dp[i-1][k]+(k-j)*fire+j*salary);                }                dp[i][j] = minn; //到第i个月的最小费用值            }        }        int minn = INF;        for(i=num[n]; i<=maxn; i++) //确定最后一个月的雇佣人数为多少时有最小值            minn = min(minn, dp[n][i]);        printf("%d\n", minn);    }    return 0;}

也附上我一开始的WA代码。。
#include<cstdio>int main(){    int n, i, j, hire, salary, fire, num[13], employee, dp;    while(~scanf("%d", &n), n)    {        scanf("%d%d%d", &hire,&salary,&fire);        for(i=1; i<=n; i++)            scanf("%d", num+i);        employee = num[1];        dp = hire*num[1]+salary*num[1];        for(i=2; i<=n; i++)        {            int minn = employee*salary, temp = employee;            if(num[i] >= employee)            {                dp += (num[i]-employee)*hire+num[i]*salary;                employee = num[i];            }            else            {                for(j=1; j<=employee-num[i]; j++)                {                    if(j*fire+(employee-j)*salary < minn)                    {                        minn = j*fire+(employee-j)*salary;                        temp = employee-j;                    }                }                employee = temp;                dp += minn;            }        }        printf("%d\n", dp);    }    return 0;}

0 0