【HDU】1158 Employment Planning
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1158
DP的难点在于构造动态转移方程,要想构造出方程,就得分析问题,找出最优解的自变量。
作专题练习的时候对DP完全没有感觉,刚拿到这道题目时也不知从哪里开始分析问题,多亏了merlininice师父后来帮我分析了这个问题,使我渐渐开始对DP有了深入的认识……(merlininice师父真是大好人那,读者以后会在我acm博文上看到更多merlininice的影子,我觉得acm是一条充满着愉快和艰辛的道路,能有人陪你一起走着,有人引导着,应该是件很开心的事。愿与所有的ACMer一起进步!)
分析思路:
设总花费为W,那么W取决于月份、以及每月实际雇佣的employee的人数(以及其变化)。
于是DP方程就出来了 DP[i][j] = min{DP[i-1][j]+cost, DP[i][j]}, cost是从i-1月变化到i月是产生的费用。
但是落实到实际代码上的时候可能还有些需要注意的问题:
1、初始化:因为这道题目要求的是花费最小,所以 DP[][] 应当初始化为尽可能大(我使用了网上流行的值:0x7FFFFFFF);
2、枚举j:j的变化应当从该月要求的employee的人数开始直至所有月份中最大的人数。(试想,如果fire一个employee的费用比给他一个月的salary都要高,并且隔了一个月之后又需要雇佣更多的人的话,那中间的那个月还不如供着他呢!)
其他应该没有什么问题了,我wa的原因是初始化的时候只用了10000,可能这个数据仍旧太小了吧?(表示很多时候大家都是被数据给坑了的…)
View Code
1 while(scanf("%d",&n)!=EOF && n){ 2 scanf("%d %d %d",&a,&b,&c); 3 max = 0; 4 for(i=0; i<n; ++i) { 5 scanf("%d",&q[i]); 6 max = max>q[i] ? max : q[i]; 7 } 8 9 for(i=0; i<15; ++i){ 10 for(j=0; j<MAXN; ++j) dp[i][j] = 0x7FFFFFFF; 11 } 12 13 for(j=q[0]; j<=max; ++j) {dp[0][j]=(b+a)*j;} 14 15 for(i=1; i<n; ++i){ 16 for(j=q[i-1]; j<=max; ++j){ 17 for(k=q[i]; k<=max; ++k){ 18 if(j>k) t=c*(j-k); 19 else t=a*(k-j); 20 t = dp[i-1][j] + t + b*k; 21 dp[i][k] = t < dp[i][k] ? t : dp[i][k]; 22 } 23 } 24 } 25 26 total = 0x7FFFFFFF; 27 for(j=q[n-1]; j<=max; ++j) { 28 total = total < dp[n-1][j] ? total : dp[n-1][j]; 29 } 30 cout<<total<<endl; 31 32 }

浙公网安备 33010602011771号