【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     }

 

posted on 2012-07-21 17:02  Yuna_  阅读(86)  评论(0)    收藏  举报