Description
Input
Output
Sample Input
3 4 5 6 10 9 11 0
Sample Output
199
大致题意:
第一行为N ,代表的季度(每个季度都是一个状态);
第二行有三个数字, hir (招聘费),sal(月薪) , fir(解雇费) ;
第三行有N个数字, 代表每个季度应该需要多少个人;
如何寻求状态方程:
对于本题,状态是针对当前(这个季度),和上一个状态(上个季度);且被上个季 度的人数影响到本季度是否招聘还是解雇;
因此有:num[13] :代表12个月(最多),每个季度需要多少个人;
dp[i][j]: 代表第i季度需求保留j个人;
状态方程:(1)如果当前状态的需求人数大于上个季度的人,则应该雇人,所以资金 费用就是 :上个季度的人的最低消费+本季度新加人的雇佣费+本季度 需求人的工资
(2) 反之,如果上个季度的人多于这个季度,则就要裁人;费用就是: 上个季度的最低消费+本季度裁的人数*遣送费+本季度人*工资
对于(1) dp[i-1][k]+(j-k)*hiring+j*salary;
(2) dp[i-1][k]+(k-j)*firing+j*salary;
只需要在两者之间找出最小值,就是dp[i][j] ,最后遍历找到最小值就行;
AC代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int dp[20][500];//*第i阶段保留j个人;
int hiring , salary , firing; //*雇佣工资,月薪,解聘工资;
int num[13];//*阶段人数
int main()
{
int month ;
while(cin>>month, month)
{
memset(dp,0,sizeof(dp));
memset(num , 0 ,sizeof(num));
int maxi = - 1 ;
cin>>hiring>>salary>>firing;
for(int i = 1 ; i <=month ;i++)
{
cin>>num[i];//*每个阶段的人数;
if(maxi<num[i])
{
maxi = num[i]; //*寻求最大雇佣人数 ;
}
}
for(int i= num[1] ; i<=maxi;i++) //*更新初始状态;
{
dp[1][i] = i*hiring + i*salary; //*第一个月基础工资
}
int mini , cost ;
for(int i= 2 ; i<= month ; i++)
{
for(int j = num[i] ; j<=maxi ; j++)
{
mini = 9999999 ;
for(int k = num[i-1] ; k <=maxi ; k++)
{
if(k<=j)
cost = dp[i-1][k]+(j-k)*hiring+j*salary;
else cost = dp[i-1][k]+(k-j)*firing+j*salary;
if(mini >cost )
mini = cost ;
}
dp[i][j] = mini ;
}
}
mini = 99999999 ;
for(int i = num[month]; i<=maxi;i++)
{
if(dp[month][i] < mini )
{
mini = dp[month][i] ;
}
}
cout << mini <<endl;
}
return 0 ;
}