问题描述:
某公司经理知道n个月中每个月所需要员工的最少人数,但是考虑到:每雇佣一个人要花费hr美元、每员工月薪为sl美元、没解雇一员工需要花费fr美元,经理发现不同的雇佣方式(每月雇佣人数不同)导致总的花费不同。该经理想知道公司n个月的最小花费。(如果某月某个员工没有工作,但没有被解雇,公司也得对其发薪金)
问题分析:
定义状态:f[i][j]为第i个月底该公司雇佣了j个员工时的最小花费,设month[i]为第i个月该公司所需员工的最少人数。弄清状态之后,再由第i-1个月向第i个月转移的过程中,第i-1个月所有的合法状态为:f[i-1][t](month[i-1]<=t<=lmt,lmt=max(month[1...n])),设转移的代价为cost,则很容易得到状态转移方程:f[i][j]=max{f[i-1][t],month[i-1]<=t<=lmt}+cost(t,j)};其中,cost(t,j)表示当前月底人数为t时,向下一个月人数为j转移时公司所要付出的花费。
代码
#include<iostream> #include<cstdio> #define Max 1001 using namespace std; int f[13][Max],hr,sl,fr,month[13]; int cost(int p,int q) { if(p<=q) return p*sl+(q-p)*(hr+sl); else return q*sl+(p-q)*fr; } int main() { int n; while(scanf("%d",&n),n) { scanf("%d%d%d",&hr,&sl,&fr); int lmt=0; for(int i=1;i<=n;i++) { scanf("%d",&month[i]); if(month[i]>lmt) lmt=month[i]; } for(int i=month[1];i<=lmt;i++) f[1][i]=i*(hr+sl);//求解第一个月不同合法状态下的花费 for(int i=2;i<=n;i++) for(int j=month[i];j<=lmt;j++) { int tmp=f[i-1][month[i-1]]+cost(month[i-1],j); for(int k=month[i-1]+1;k<=lmt;k++) { int r=f[i-1][k]+cost(k,j); if(r<tmp) tmp=r; } f[i][j]=tmp; } int cnt=f[n][month[n]]; for(int i=month[n]+1;i<=lmt;i++) if(f[n][i]<cnt) cnt=f[n][i]; printf("%d/n",cnt); } return 0; }