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\n",ans);
43     }
44     return 0;
45 }

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

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

第二天:继续不懂==

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

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

时间: 2024-08-03 21:18:13

HDU 1158 Employment Planning【DP】的相关文章

HDU 1158 Employment Planning (DP)

Problem Description A project manager wants to determine the number of the workers needed in every month. He does know the minimal number of the workers needed in each month. When he hires or fires a worker, there will be some extra cost. Once a work

hdu 1158 Employment Planning(DP)

题意: 有一个工程需要N个月才能完成.(n<=12) 给出雇佣一个工人的费用.每个工人每个月的工资.解雇一个工人的费用. 然后给出N个月所需的最少工人人数. 问完成这个项目最少需要花多少钱. 思路: 将(i,num):[第i个月拥有num个工人 ]看成一个状态.那么就想到用DP. 看代码 代码: struct node{ int minNum, maxNum; } month[15]; int n; int hire,salary,fire; int dp[15][505]; int main(

HDU 1158 Employment Planning

题意:有一公司要工作n个月每个月需要至少p[i]个人工作,每个人的工资固定位m, 每雇佣一个人要花费h,每炒掉一个人要花费f.求完成n个月工作,公司最小的花费. 思路: Dp[i][j]为前i个月的留j个人的最优解;p[i]<=j<=Max{p[i]}; j>Max{p[i]}之后无意义,无谓的浪费 记Max_n=Max{p[i]}; Dp[i-1]中的每一项都可能影响到Dp[i],即使p[i-1]<<p[i] 所以利用Dp[i-1]中的所有项去求Dp[i]; 对于p[i]&

hdu 4908 BestCoder Sequence【DP】

题目链接 :http://acm.hdu.edu.cn/showproblem.php?pid=4908 题目大意:给出一个排列,一个m,求出这个排列的连续子序列中有多少个序列式以m为中位数. 由于是一个排列,不会出现重复的数字,记录一下m的位置index,然后以index为分界线,往左求出s[i](表示从i到index之间有多少大于m),b[i](表示从i到index之间有多少小于m),往右求出s[i](表示从index到i之间有多少大于m),b[i](表示从index到i之间有多少小于m).

HDU1158_Employment Planning【DP】

Employment Planning Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3814    Accepted Submission(s): 1574 Problem Description A project manager wants to determine the number of the workers neede

Hdu 1158 Employment Planning(DP)

Problem地址:http://acm.hdu.edu.cn/showproblem.php?pid=1158 一道dp题,或许是我对dp的理解的还不够,看了题解才做出来,要加油了. 只能先上代码了. #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int MAXN = 100 + 28; int dp[15][MAXN]; int workers[

HDU 1421 搬寝室【DP】

解题思路:给定n个物品,每次搬运两个,问怎样搬运疲劳度最小 发现自己根本想不出来dp[i][j]应该表示什么状态-----,这道题唯一想得沾边一点的就是要对这n件物品排序(因为相邻的话才会疲劳度最小----)---- 还是看的题解------- 下面是看了题解之后的一点体会--- 用dp[i][j]表示在前i件物品里面取j对时的最小疲劳度 (1)i==2*j 那么前i件物品我们全部选择了,所以dp[i][j]=dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]) (2

hdu 1058 Humble Numbers【dp】

题目链接:http://acm.acmcoder.com/showproblem.php?pid=1058 题意:数字只有2,3,5,7素因子的数叫做Humble Number,问你第 n 个Humble Number是什么? 解法:枚举. 代码: #include <stdio.h> #include <string.h> #include <vector> #include <string> #include <algorithm> #inc

HDU 1505 City Game【DP】

题意:是二维的1506,即在1506的基础上,再加一个for循环,即从第一行到最后一行再扫一遍--- 自己写的时候,输入的方法不对---发现输不出结果,后来看了别人的[email protected][email protected]发现是将字母和空格当成一个字符串来输入的. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace st