题目链接:

acm.hdu.edu.cn/showproblem.php?pid=1158

Employment Planning

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6020    Accepted Submission(s): 2609

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 worker is hired, he will get the salary even if he is not working. The manager knows the costs of hiring a worker, firing a worker, and the salary of a worker. Then the manager will confront such a problem: how many workers he will hire or fire each month in order to keep the lowest total cost of the project.
 
Input
The input may contain several data sets. Each data set contains three lines. First line contains the months of the project planed to use which is no more than 12. The second line contains the cost of hiring a worker, the amount of the salary, the cost of firing a worker. The third line contains several numbers, which represent the minimal number of the workers needed each month. The input is terminated by line containing a single '0'.
 
Output
The output contains one line. The minimal total cost of the project.
 
Sample Input
3
4 5 6
10 9 11
0
 
Sample Output
199
 
Source
 
 
题意:
一家公式完成一个项目,需要n个月的时间,每个月至少雇佣a1...an个工人,解雇工人和雇佣工人都需要一定的费用,每个月还要给雇来的工人工资,问你最少的花费是多少(不用输出方案,只有输出最优解)
分析:
解雇和雇佣工人都需要一定的费用,现在就是要看每个月怎么对工人进行解雇和雇佣的操作可以使得花费最少,每个月雇佣的工人可以>=这个月必须雇佣的工人数目,具体拿样例分析
3
4 5 6
10 9 11
代表3个月份,雇佣工人耗费4,一个雇佣的工人每月工资5,解雇工人耗费6
第一个月至少雇佣10个人,第二个月至少雇佣9个人,第三个月至少雇佣11个人
做法:
该3个月份中最大工人数目为11,最小工人数目为9
第一个月我们可以雇佣10个工人,或者11个工人
第二个月我们需要的工人底线是9个,如果该月雇佣9个(需要解雇x人,x由上一个月雇佣人数决定(上一个月人数减去9),如果该月雇佣10个人(需要解雇人数x,也由上一个月雇佣人数决定),如果该月雇佣11个人,那么现在我们可能还需要继续的雇佣工人,
第三个月也依次类推,
这样不同的雇佣策略导致我们的花费肯定不同,在这些方案在花费中找到最小的即可
 
dp的关键在于明白:前面一个月雇佣多少个人使得这个月的花费最小
 dp[i][j] :代表在第i个月的时候,雇佣J个人的总费用(雇佣费+工资)
dp[i][j]=dp[i-1][k](前面一个月雇佣k个人,可以使得前面的i个月(包括i)的花费最小)+这个月的费用
          =dp[i-1][k]+abs(j-k)*v+j*工资  v表示解雇或者雇佣的权值,由j,k相对大小决定
注意点:
1.要知道每月需要工人的max和min(保证每月雇佣人数在这个集合之间,[min,max]),这样每个月雇佣的人数不同,花费也不同,才可以求解最优解
2.初始化 第一个月的时候需要手动初始化,拿样例说,dp[1][9]第一个月雇佣9个人的费用(雇佣费加工资).......................dp[1][11]第一个月雇佣11个人的费用(雇佣费加工资),需要手动初始化
3.最有解是在dp[n][j]中找最小的,j属于[min,max]集合
 
重点:前面一个月雇佣多少人使得前面月份加上这个月份的花费最小
 
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define inf 9999999
int dp[][];
int a[];
int hire,salary,fire;
int main()
{
int n;
while(~scanf("%d",&n))
{
if(n==)
break;
scanf("%d %d %d",&hire,&salary,&fire);
int max_people=-inf,min_people=inf;
for(int i=; i<=n; i++)
{
scanf("%d",&a[i]);
max_people=max(max_people,a[i]);
min_people=min(min_people,a[i]);
}
//dp[i][j] 在第i个月的时候,雇佣j个人的总费用(雇佣费+工资) //dp初始化
memset(dp,0x3f,sizeof(dp));//无穷大
for(int j=min_people; j<=max_people; j++)
{
dp[][j]=hire*j+salary*j;
} for(int i=; i<=n; i++)
{
for(int j=a[i]; j<=max_people; j++)
{
int t=inf;
for(int k=a[i-]; k<=max_people; k++)
{
int v=hire;
if(k-j>)//解雇
{
v=fire;
}
int x=dp[i-][k]+abs(k-j)*v+j*salary;
t=min(t,x);
}
dp[i][j]=t;
}
}
int t=inf;
for(int j=; j<=max_people; j++)
{
t=min(t,dp[n][j]);
}
printf("%d\n",t);
}
}

ojbk,溜了溜了,吃饭去

 
 
 
 
 
 
 
 
 
 

HDU 1158(非常好的锻炼DP思维的题目,非常经典)的更多相关文章

  1. HDU 1158 Employment Planning (DP)

    题目链接 题意 : n个月,每个月都至少需要mon[i]个人来工作,然后每次雇佣工人需要给一部分钱,每个人每个月还要给工资,如果解雇人还需要给一笔钱,所以问你主管应该怎么雇佣或解雇工人才能使总花销最小 ...

  2. hdu 1158 dp Employment Planning

    Employment Planning Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u ...

  3. HDU 1024 Max Sum Plus Plus --- dp+滚动数组

    HDU 1024 题目大意:给定m和n以及n个数,求n个数的m个连续子系列的最大值,要求子序列不想交. 解题思路:<1>动态规划,定义状态dp[i][j]表示序列前j个数的i段子序列的值, ...

  4. HDU 1231 最大连续子序列 --- 入门DP

    HDU 1231 题目大意以及解题思路见: HDU 1003题解,此题和HDU 1003只是记录的信息不同,处理完全相同. /* HDU 1231 最大连续子序列 --- 入门DP */ #inclu ...

  5. hdu 4778 Gems Fight! 博弈+状态dp+搜索

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4102743.html 题目链接:hdu 4778 Gems Fight! 博弈+状态dp+搜 ...

  6. hdu 4514 并查集+树形dp

    湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tot ...

  7. hdu 3247 AC自动+状压dp+bfs处理

    Resource Archiver Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Ot ...

  8. hdu 2825 aC自动机+状压dp

    Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  9. hdu 3433 A Task Process 二分+dp

    A Task Process Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

随机推荐

  1. CodeForces 598A(水)

    还是要注意int和long long的范围,以及double型的问题 pow函数经常会报一个double型的错,参考这篇文章 http://blog.csdn.net/lawrencesgj/arti ...

  2. Spring入门(三)— AOP注解、jdbc模板、事务

    一.AOP注解开发 导入jar包 aop联盟包. aspectJ实现包 . spring-aop-xxx.jar . spring-aspect-xxx.jar 导入约束 aop约束 托管扩展类和被扩 ...

  3. jQuery bind()与delegate()的区别

    笔试题: bind()与delegate()的区别主要有三点: 1 绑定目标 .bind直接绑在目标元素上 .delegate绑在父元素上 2  监听个数 .bind监听个数多——每个目标元素都需要添 ...

  4. JavaScript高级编程———数据存储(cookie、WebStorage)

    JavaScript高级编程———数据存储(cookie.WebStorage) <script> /*Cookie 读写删 CookieUtil.get()方法根据cookie的名称获取 ...

  5. Windows 环境下 NodeJs 开发 Log

    安装 NodeJs, npm. 环境变量配置. 1, Grunt 安装 :  npm install -g grunt-clinpm install -g grunt package.json { & ...

  6. POJ P2828 Buy Ticket——线段树的其他信息维护

    Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get ...

  7. 【javascript】javasrcipt设计模式之状态模式

    使用场景 解决多个[ifelse]嵌套,将其封装成若干个方法 区分事物内部的状态,事物内部的状态的改变往往会带来事物的行为的改变 简单的多个状态直接切换的时候 //两个状态之间的切换,使用if-els ...

  8. Fragment 重叠 遮盖问题

    1.导致Fragment 重叠 和遮盖的原因 主要还是因为Fragment的状态保存机制,当系统内存不足时,Fragment的主Activity被回收,Fragment的实例并没有随之被回收. Act ...

  9. redis 序列化get、set获取不到原因记录

    最近项目里面出现了个bug,把数据从数据库中读取后又存取到redis里面,之后再读取.奇怪的是,有一个 字段读取不到. public class Circle { private String id; ...

  10. Java 设计模式(三)-单例模式(Singleton Pattern)

    1     概念定义 1.1   定义 确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 1.2   类型 创建类模式 1.3   难点 1)多个虚拟机 当系统中的单例类被拷贝运行在多 ...