题意:列出每个月需要的员工数,已知每月工资、以及雇佣和开除员工的额外费用,求最小的预算。(只要员工不被开除就拿工资)
分析:开始我想的一维dp,结果在找状态转移方程的时候发现有很多情况要讨论,所以我就认为这题应该是一个贪心题,在准备打代码的时候发现贪心不能得出最优解,所以我就去搜题解了,原来是二维dp。记住一维要分很多情况的要用二维。
dp[i][j]表示第i月用j个员工时前i月的最小预算,j从a[i]枚举到mx(n个月中需要的最多的员工数),状态转移方程:dp[i][j]=min(dp[i-1][k]+cost),其中a[i-1]<=k<=mx, cost表示从dp[i-1][k]状态转移到dp[i][j]状态的开销;所以最终结果ans=min(dp[n][k]),a[n]<=k<=mx
代码:
#include<iostream> #define INF 1000000007 using namespace std; int n,fire,salary,hire; int a[20],dp[20][200000]; int main() { while(cin>>n){ if(!n) break; cin>>hire>>salary>>fire; int mx=-1; for(int i=1;i<=n;i++){ cin>>a[i]; if(mx<a[i]) mx=a[i]; } for(int i=a[1];i<=mx;i++) dp[1][i]=hire*i+salary*i; for(int i=2;i<=n;i++){ for(int j=a[i];j<=mx;j++){ int mi=INF; for(int k=a[i-1];k<=mx;k++){ int tmp; if(k>j) tmp=dp[i-1][k]+(k-j)*fire+salary*j; else tmp=dp[i-1][k]+(j-k)*hire+salary*j; if(mi>tmp) mi=tmp; } dp[i][j]=mi; } } int mi=INF; for(int i=a[n];i<=mx;i++) if(mi>dp[n][i]) mi=dp[n][i]; cout<<mi<<endl; } }
!HDU 1158 Employment Planning--DP--(二维)
原文地址:http://blog.csdn.net/ac_0_summer/article/details/46400101