• 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 }
  • 相关阅读:
    指针变量的值和指针变量地址
    定时备份docker容器中mysql的数据
    sql server表外键查询
    Go语言strings包基本操作
    centos安装字体库处理中文乱码
    codeforces 1610D
    汽车配件生产加工企业管理软件出售生产加工刹车盘、刹车鼓、刹车蹄、刹车片等企业通用
    关于document.onmousemove报错Invalid or unexpected token问题
    SilverLight支持的DataTable可以直接绑定
    我的工作我的状态
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/2441202.html
Copyright © 2020-2023  润新知