zoukankan      html  css  js  c++  java
  • ZOJ 1454 Employment Planing

    这个题目是上个礼拜天上午看的,纠结了一上午啊,总算还是有点思路,但是总是感觉到相当的混乱,感觉被伤到了一样。后来想想不必就为这么一个题目纠结,换一个吧。但是不纠结是不可能的。最终,还是没忍住,看了一下人家的解题报告,发现思路大致上还是对的,但是,细节方面处理的很烂,琢磨了半天,几乎都要把人家的代码背下来了。今天早上一起来,就决心把这个伤到我的题目弄掉,但是,因为一个小小的BUG,弄了好一下,我算是明白了,写点代码还是老实点的好啊,免得因为一个BUG要调试半天。。

    现在说正题。题目的意思是,老板需要雇人干活,雇佣一个人需要钱h,每个月需要支付他工资s,解雇他还要给他"买断”,需要支付f的钱。现在告诉你月份数m,然后分别给你h,s,f,然后是m个月中每个月需雇佣的最少的人数a[i],求支出最少的结果。

    首先,贪心的思路是应该否定的,假设我们按照每个月都恰好雇佣最少需要的人数,那么在雇佣费h和解雇费f很低的情况下,是有可能靠谱的。但是,假设雇佣费或者解雇费很高,而工资很低,那我们宁可让个别人吃空饷,而不去重新雇佣他们或者说事去解雇他们。

    那么,这个题目就应该用DP来解决了。假设截止第i个月为止,可能雇佣的最大人数为m[i](m[i]=max{a[1],a[2],…………,a[n]}),这样就可以考虑到为少支出让部分人吃空饷的状况了。令dp[i][j]表示到第i个月时雇佣j人时支出的最小值,那么我们可以得到装填转移方程:dp[i][j]=min{dp[i-1][k]+(j-k)*h+j*s,dp[i-1][r]+(r-j)*f+j*s}其中k<j,m[i]>=r>=j.

    接下来,处理好细节就可以了。

    下面贴代码:

    View Code
     1 #include <iostream>
     2 #include <cstring>
     3 using namespace std;
     4 int main()
     5 {
     6     int a[13],m[13],*dp[13];
     7     int month,i,j,k,temp,min,max,h,s,f;
     8     while(cin>>month)
     9     {
    10         if(month == 0)
    11             break;
    12         cin>>h>>s>>f;
    13         for(i = 1;i <= month;i++)
    14             cin>>a[i];
    15         max = a[1];
    16         for(i = 1;i <= month;i++)
    17         {
    18             if(a[i] > max)
    19                 max = a[i];
    20             dp[i] = new int [max + 1];
    21             m[i] = max;
    22         }
    23         for(i = 1;i <= month;i++)
    24             for(j = 0;j <= m[i];j++)
    25                 dp[i][j] = 0;
    26         dp[1][a[1]] = a[1] * (h + s);
    27         for(i = 2;i <= month;i++)
    28             for(j = a[i];j <= m[i];j++)
    29             {
    30                 min = 0xffffff;
    31                 for(k = a[i - 1];k <= m[i - 1]&&k < j;k++)
    32                     if(dp[i - 1][k])
    33                     {
    34                         temp = dp[i - 1][k] + (j - k) * h + j * s;
    35                         if(temp < min)
    36                             min = temp;
    37                     }
    38                 for(k = j;k <= m[i - 1];k++)
    39                     if(dp[i - 1][k])
    40                     {
    41                         temp = dp[i - 1][k] + (k - j) * f + j * s;
    42                         if(temp < min)
    43                             min = temp;
    44                     }
    45                 dp[i][j] = min;
    46             }//for j
    47         min = 0xffffff;
    48         for(i = 1;i <= m[month];i++)
    49             if(dp[month][i])
    50                 if(dp[month][i] < min)
    51                     min = dp[month][i];
    52         /*for(i = 1;i <= m[month];i++)
    53             cout<<dp[month][i]<<" ";
    54         cout<<endl;*/
    55         cout<<min<<endl;
    56         for(i = 1;i <= month;i++)
    57             delete[] dp[i];
    58     }//while
    59     return 0;
    60 }
  • 相关阅读:
    windows的80端口被占用时的处理方法
    Ansible自动化运维工具安装与使用实例
    Tomcat的测试网页换成自己项目首页
    LeetCode 219. Contains Duplicate II
    LeetCode Contest 177
    LeetCode 217. Contains Duplicate
    LeetCode 216. Combination Sum III(DFS)
    LeetCode 215. Kth Largest Element in an Array(排序)
    Contest 176 LeetCode 1354. Construct Target Array With Multiple Sums(优先队列,递推)
    Contest 176
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/2441202.html
Copyright © 2011-2022 走看看