• HDU 1158 Employment Planning【DP】


    题意:给出n个月,雇佣一个人所需的钱hire,一个人工作一个月所需要的钱salary,解雇一个人所需要的钱fire,再给出这n个月每月1至少有num[i]个人完成工作,问完成整个工作所花费的最少的钱是多少。

    用dp[i][j]表示在第i个月雇佣j个人所需要的最少花费

    先考虑只解雇人和聘请人的情况

    1 for(j=num[i];j<=sum;j++)
    2             {
    3                 if(j>num[i-1])//说明雇佣了人 
    4                 dp[i][j]=dp[i-1][num[i-1]]+j*salary+(j-num[i-1])*hire;
    5                 else//说明解聘了人 
    6                 dp[i][j]=dp[i-1][num[i-1]]+j*salary+(num[i-1]-j)*fire;
    7 }

    再考虑状态转移,可以举一个例子--
    假如一个人的工资是5元,但是解雇他要花500元,这样比较下,把这个人留在下一个月继续工作显然开销会小很多,同理对于k个人也是一样的。

    1 for(k=num[i-1]+1;k<=sum;k++)
    2                 {
    3                 if(k<j) //不够下一个月的人数,需要聘请人 
    4                 dp[i][j]=min(dp[i][j],dp[i-1][k]+j*salary+(j-k)*hire);
    5                 else//超过下一个 月的人数,需要解雇人 
    6                 dp[i][j]=min(dp[i][j],dp[i-1][k]+j*salary+(k-j)*fire);
    7                 }

    然后就是初始化,对于第一个月, 花的钱为:(hire+salary)*人数

    最后扫一遍最后一个月雇佣不同人数(在满足人数大于num[n-1]的情况下),得出最小值。

     1 #include<iostream>  
     2 #include<cstdio>  
     3 #include<cstring>  
     4 #include<algorithm>  
     5 using namespace std;
     6 
     7 int dp[15][1005];
     8 int num[15];
     9 
    10 int main()
    11 {
    12     int n,i,j,k,ans,hire,salary,fire,sum;
    13     while(scanf("%d",&n)!=EOF&&n)
    14     {   sum=-5;
    15         scanf("%d %d %d",&hire,&salary,&fire);
    16         for(i=0;i<n;i++) {scanf("%d",&num[i]);sum=max(sum,num[i]);}
    17         memset(dp,0,sizeof(dp));
    18     
    19         for(i=num[0];i<=sum;i++)
    20         dp[0][i]=i*(hire+salary);
    21         
    22         for(i=1;i<n;i++)
    23         {
    24             for(j=num[i];j<=sum;j++)
    25             {
    26                 if(j>num[i-1])//说明雇佣了人 
    27                 dp[i][j]=dp[i-1][num[i-1]]+j*salary+(j-num[i-1])*hire;
    28                 else//说明解聘了人 
    29                 dp[i][j]=dp[i-1][num[i-1]]+j*salary+(num[i-1]-j)*fire;
    30                 for(k=num[i-1]+1;k<=sum;k++)
    31                 {
    32                 if(k<j) //不够下一个月的人数,需要聘请人 
    33                 dp[i][j]=min(dp[i][j],dp[i-1][k]+j*salary+(j-k)*hire);
    34                 else//超过下一个 月的人数,需要解雇人 
    35                 dp[i][j]=min(dp[i][j],dp[i-1][k]+j*salary+(k-j)*fire);
    36                 }
    37             }
    38         }
    39         ans=10000005;
    40         for(i=num[n-1];i<=sum;i++)
    41         ans=min(ans,dp[n-1][i]);
    42         printf("%d
    ",ans);
    43     }
    44     return 0;
    45 }
    View Code

    这一题= =没有想出状态,没有想出方程= =全程看题解===还看了3天--55555

    第一天:读懂了题目==木有思路

    第二天:继续不懂==

    第三天:看题解= =懂一丢丢= =

    大概一道题目,一时不会,放着慢慢来,每天看一看,可能就会好一些 加油加油---go---go---

  • 相关阅读:
    个人日志-6.27
    <软件工程>课程总结
    团队项目--地铁信息查询-UML图初步设计
    7-4 日报
    7-5小组日报 最终版的发布
    7-1 7-3
    软工日报6-30
    软工日报 6-29
    6-28小组会议记录
    6-27小组讨论内容
  • 原文地址:https://www.cnblogs.com/wuyuewoniu/p/4296980.html
Copyright © 2020-2023  润新知