标签:
题意:给出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---
HDU 1158 Employment Planning【DP】
标签:
原文地址:http://www.cnblogs.com/wuyuewoniu/p/4296980.html