POJ 2586 Y2K Accounting Bug(贪心+枚举)

原题地址

http://poj.org/problem?id=2586

题意:已知每个月的经营状况要么盈利s,要么亏损d,若每五个月的汇总都是亏损,求这一年12个月最大盈利额(不能盈利则输出Deficit)。

解题思路

这道题被划分到贪心的题库里,但是其实不用花时间在贪心算法的设计上。

最直观的贪心思路就是,为了使每5个月亏损且总和盈利,那就要利用相邻的5个月的重叠部分,将亏损的月份放在这些部分且使每5个月的亏损值最小。即:让亏损的月份在尽量往后排,向右辐射。

以测试样例为例,每个月要么盈利59,要么亏损237,根据上面的贪心思想,做出一下安排:
1. 先处理1-5月,不难发现,在前4个月盈利后1个月亏损的安排下,保证了5个月经营之和为负,且亏损额尽可能少。因此,每5个月4s1d是这次例子的贪心模式。
2. 再处理之后的与安排亏损的5月份有交集的每5个月,对于2-6月由于5月份已经安排过d,所以6月份继续排s,3-7月、4-8月、5-9月以此类推…
3. 再处理6-10月时重复1-5月的安排,剩余的月份参照步骤2的安排。
4. 统计盈利月份数=10,亏损月份数=2,全年经营之和即10*59-2*237=+116

由于这道题比较简单,我们可以手动模拟推出每5个月在不同s、d组合下,找到使全年盈利额最大的贪心模式、全年盈利及亏损月份数

  • SSSSDSSSSDSS(4s 1d,总计10s 2d)
  • SSSDDSSSDDSS(3s 2d,总计8s 4d)
  • SSDDDSSDDDSS(2s 3d,总计6s 6d)
  • SDDDDSDDDDSD(1s 4d,总计3s 9d)
  • DDDDDDDDDDDD(0s 5d,总计0s 12d)

AC代码

#include <iostream>

using namespace std;

int main()
{
    int s, d, dSeason, sum; //dSeason指每五个月亏损最少需要几个d
    int dYear[] = {2, 4, 6, 9, 12}; //每五个月里需要的d造成的年亏损月份数
    while (cin >> s >> d)
    {
        dSeason = 1; //至少亏损一个月
        while ((5-dSeason)*s - dSeason*d > 0) ++dSeason;
        sum = (12-dYear[dSeason-1])*s - dYear[dSeason-1]*d; //年净收入
        if (sum < 0) cout << "Deficit" << endl;
        else cout << sum << endl;
    }
    return 0;
}

内存占用:224K 耗时:32ms
算法复杂度:O(1)

posted @ 2017-04-07 14:28  Lecholin  阅读(116)  评论(0编辑  收藏  举报