ZOJ 1454 Employment Planing

这个题目是上个礼拜天上午看的,纠结了一上午啊,总算还是有点思路,但是总是感觉到相当的混乱,感觉被伤到了一样。后来想想不必就为这么一个题目纠结,换一个吧。但是不纠结是不可能的。最终,还是没忍住,看了一下人家的解题报告,发现思路大致上还是对的,但是,细节方面处理的很烂,琢磨了半天,几乎都要把人家的代码背下来了。今天早上一起来,就决心把这个伤到我的题目弄掉,但是,因为一个小小的BUG,弄了好一下,我算是明白了,写点代码还是老实点的好啊,免得因为一个BUG要调试半天。。

现在说正题。题目的意思是,老板需要雇人干活,雇佣一个人需要钱h,每个月需要支付他工资s,解雇他还要给他"买断”,需要支付f的钱。现在告诉你月份数m,然后分别给你h,s,f,然后是m个月中每个月需雇佣的最少的人数a[i],求支出最少的结果。

首先,贪心的思路是应该否定的,假设我们按照每个月都恰好雇佣最少需要的人数,那么在雇佣费h和解雇费f很低的情况下,是有可能靠谱的。但是,假设雇佣费或者解雇费很高,而工资很低,那我们宁可让个别人吃空饷,而不去重新雇佣他们或者说事去解雇他们。

那么,这个题目就应该用DP来解决了。假设截止第i个月为止,可能雇佣的最大人数为m[i](m[i]=max{a[1],a[2],…………,a[n]}),这样就可以考虑到为少支出让部分人吃空饷的状况了。令dp[i][j]表示到第i个月时雇佣j人时支出的最小值,那么我们可以得到装填转移方程:dp[i][j]=min{dp[i-1][k]+(j-k)*h+j*s,dp[i-1][r]+(r-j)*f+j*s}其中k<j,m[i]>=r>=j.

接下来,处理好细节就可以了。

下面贴代码:

View Code
 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 int main()
 5 {
 6     int a[13],m[13],*dp[13];
 7     int month,i,j,k,temp,min,max,h,s,f;
 8     while(cin>>month)
 9     {
10         if(month == 0)
11             break;
12         cin>>h>>s>>f;
13         for(i = 1;i <= month;i++)
14             cin>>a[i];
15         max = a[1];
16         for(i = 1;i <= month;i++)
17         {
18             if(a[i] > max)
19                 max = a[i];
20             dp[i] = new int [max + 1];
21             m[i] = max;
22         }
23         for(i = 1;i <= month;i++)
24             for(j = 0;j <= m[i];j++)
25                 dp[i][j] = 0;
26         dp[1][a[1]] = a[1] * (h + s);
27         for(i = 2;i <= month;i++)
28             for(j = a[i];j <= m[i];j++)
29             {
30                 min = 0xffffff;
31                 for(k = a[i - 1];k <= m[i - 1]&&k < j;k++)
32                     if(dp[i - 1][k])
33                     {
34                         temp = dp[i - 1][k] + (j - k) * h + j * s;
35                         if(temp < min)
36                             min = temp;
37                     }
38                 for(k = j;k <= m[i - 1];k++)
39                     if(dp[i - 1][k])
40                     {
41                         temp = dp[i - 1][k] + (k - j) * f + j * s;
42                         if(temp < min)
43                             min = temp;
44                     }
45                 dp[i][j] = min;
46             }//for j
47         min = 0xffffff;
48         for(i = 1;i <= m[month];i++)
49             if(dp[month][i])
50                 if(dp[month][i] < min)
51                     min = dp[month][i];
52         /*for(i = 1;i <= m[month];i++)
53             cout<<dp[month][i]<<" ";
54         cout<<endl;*/
55         cout<<min<<endl;
56         for(i = 1;i <= month;i++)
57             delete[] dp[i];
58     }//while
59     return 0;
60 }
posted @ 2012-04-10 20:25  浙西贫农  阅读(221)  评论(0编辑  收藏  举报