• HDU 1158 Employment Planning


    又一次看题解。

    万事开头难,我想DP也是这样的。

    呵呵,不过还是有进步的。

    比如说我一开始也是打算用dp[i][j]表示第i个月份雇j个员工的最低花费,不过后面的思路就完全错了。。

    不过这里还有个问题,这样开数组j开多大比较好,难道要我开2^31-1这么大?

    题解里面开了1000多,也许再小一点也能过吧。

    因为有可能解雇一个人的花费比较大,所以某个月可能继续雇佣他这样总的算来是最省的。

    所以第i个月可能雇佣的人数是从num[i] ~ NumMax。

    首先对第一个月的费用初始化,就是(雇佣+薪水)×人数。

    后面便是核心代码,

    1 if(j < num[i - 1])
    2                     dp[i][j] = dp[i - 1][num[i - 1]] + salary * j + (num[i - 1] - j) * fire;
    3                 else
    4                     dp[i][j] = dp[i - 1][num[i - 1]] + salary * j + (j - num[i - 1]) * hire;

    这一句是为了后面的状态转移做准备,

    先假设在上个月恰好雇num[i - 1]人的最小费用的基础上,人数多了就解雇,少了就雇佣是最省的。

    然后再增加一个循环变量k,假如上个月多雇了一个人,那么这个月不用解雇也许可能更省。

    1 for(int k = num[i - 1] + 1; k <= NumMax; ++k)
    2                 {
    3                     if(k > j)
    4                         dp[i][j] = min(dp[i][j], dp[i - 1][k] + j * salary + (k - j) * fire);
    5                     else
    6                         dp[i][j] = min(dp[i][j], dp[i - 1][k] + j * salary + (j - k) * hire);
    7                 }

    最后就是输出最优解了,最优解有可能在数组最后一行的任何一个地方(还是那句话,假如上个月多雇了一个人,那么这个月不用解雇也许可能更省。)

    所以要找到最后一行的最小值来输出。

    总结:

    注意:千万不要的在心情不平稳的时候敲代码,这样只会越敲越乱,与其去改还不如心平气和的从头开始敲,好有个完整的思路。

    刚才9点多在教室里是时候因为要快熄灯了,而且这一天就在搞这一道题,还没完全弄明白。便有些心急,想着今天怎么也要把这道题

    A出来。结果回宿舍改的时候各种错误,变量名打错,不等号搞反之类的。

    不管是做题还是敲代码,平心静气,切记切记!

    完整的AC代码:

     1 #define LOCAL
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 int dp[15][1200];
     9 int num[15];
    10 
    11 int main(void)
    12 {
    13     #ifdef LOCAL
    14         freopen("1158in.txt", "r", stdin);
    15     #endif
    16 
    17     int n;
    18     while(scanf("%d", &n) && n)
    19     {
    20         int i;
    21         int fire, salary, hire;
    22         int NumMax = 0;
    23         scanf("%d %d %d", &hire, &salary, &fire);
    24         
    25         for(i = 0; i < n; ++i)
    26         {
    27             scanf("%d", &num[i]);
    28             if(NumMax < num[i])
    29                 NumMax = num[i];
    30         }
    31         if(NumMax == 0)
    32         {
    33             printf("0
    ");
    34             continue;
    35         }
    36         for(i = num[0]; i <= NumMax; ++i)
    37             dp[0][i] = i * (hire + salary);
    38 
    39         for(i = 1; i < n; ++i)
    40         {
    41             for(int j = num[i]; j <= NumMax; ++j)
    42             {
    43                 if(j < num[i - 1])
    44                     dp[i][j] = dp[i - 1][num[i - 1]] + salary * j + (num[i - 1] - j) * fire;
    45                 else
    46                     dp[i][j] = dp[i - 1][num[i - 1]] + salary * j + (j - num[i - 1]) * hire;
    47             
    48                 //考虑到与其解雇一个人还不如让他继续待下去的情况
    49                 for(int k = num[i - 1] + 1; k <= NumMax; ++k)
    50                 {
    51                     if(k > j)
    52                         dp[i][j] = min(dp[i][j], dp[i - 1][k] + j * salary + (k - j) * fire);
    53                     else
    54                         dp[i][j] = min(dp[i][j], dp[i - 1][k] + j * salary + (j - k) * hire);
    55                 }
    56             }
    57         }
    58 
    59         int ans = 2000000000;
    60         for(i = num[i - 1]; i <= NumMax; ++i)
    61             ans = min(dp[n - 1][i], ans);
    62         printf("%d
    ", ans);
    63     }
    64     return 0;
    65 }
    代码君
  • 相关阅读:
    2-4 递增链表的插入 链表
    KMPnext数组自看
    Shortest Prefixes POJ
    Xor Sum HDU
    Immediate Decodability HDU
    Repository HDU
    "strcmp()" Anyone? UVA
    Remember the Word UVALive
    A Magic Lamp HDU
    Check Corners HDU
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/3826533.html
Copyright © 2020-2023  润新知