• 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 }
    代码君
  • 相关阅读:
    2017ccpc全国邀请赛(湖南湘潭) E. Partial Sum
    Codeforces Round #412 C. Success Rate (rated, Div. 2, base on VK Cup 2017 Round 3)
    2017 中国大学生程序设计竞赛 女生专场 Building Shops (hdu6024)
    51nod 1084 矩阵取数问题 V2
    Power收集
    红色的幻想乡
    Koishi Loves Segments
    Wood Processing
    整数对
    Room and Moor
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/3826533.html
Copyright © 2020-2023  润新知