HDOJ 1158 DP

DP公式个人感觉如下ans[m][i]=min(ans[m-1][k]+diff),对每个need[m-1]<=k<=maxNeed。其中,m是大于等于2的月份(1月份的ans直接初始化)。need数组存放某月需要的员工数,maxNeed需要员工数最多的月份的员工数。diff是员工数从(m-1)月的 i 变成这个m月的k所需要支付的差值。

这个公式想出来以后,发现题目没有给员工数的最大数量,如果员工数很多,假设为10000,则最大运算量为12*10000*10000,上十亿了。如果是这样肯定是要超时的。其实,后来发现输入数据中每月的员工数量是不超过1000的,这样,最大运算量不超过千万,所以可以过。

#include <iostream>
using namespace std;

const int MAX_MONTH = 12;
const int MAX_STAFF = 10000;

int ans[MAX_MONTH + 1][MAX_STAFF];

inline int getMin(int a,int b)
{
    return a < b ? a : b;
}

int main ()
{
    int month,maxNeed = -1;
    int hire,salary,fire;
    int need[MAX_MONTH + 1];
    while (scanf("%d",&month) != -1 && month != 0)
    {
        memset(ans,0,sizeof(ans));
        scanf("%d%d%d",&hire,&salary,&fire);
        for (int i = 1;i <= month;i ++)
        {
            scanf("%d",&need[i]);
            maxNeed = maxNeed > need[i] ? maxNeed : need[i];
        }
        for (int i = need[1];i <= maxNeed;i ++)/* 第一个月的需要初始化 */
            ans[1][i] = (hire + salary) * i;
        for (int i = 2;i <= month;i ++)
        {
            for (int j = need[i];j <= maxNeed;j ++)/* 这个月的雇员数量 */
            {
                int minNeed = -1;
                for (int k = need[i - 1];k <= maxNeed;k ++)/* 上个月的雇员数量 */
                {
                    if (k < j)/* 上个月的雇员数比这个月少 */
                    {
                        if (minNeed == -1)
                            minNeed = ans[i - 1][k] + hire * (j - k) + salary * j;
                        else
                            minNeed = getMin(minNeed,ans[i - 1][k] + hire * (j - k) + salary * j);
                    }
                    else/* 上个月雇员数大于等于这个月的 */
                    {
                        if (minNeed == -1)
                            minNeed = ans[i - 1][k] + fire * (k - j) + salary * j;
                        else
                            minNeed = getMin(minNeed,ans[i - 1][k] + fire * (k - j) + salary * j);
                    }
                }
                ans[i][j] = minNeed;
            }
        }
        int min = -1;
        for (int i = need[month];i <= maxNeed;i ++)
        {
            if (min == -1)
                min = ans[month][i];
            else
                min = getMin(min,ans[month][i]);
        }
        printf("%d\n",min);
    }
    return 0;
}
posted @ 2012-08-12 20:28  peaceful  阅读(142)  评论(0)    收藏  举报