原题地址
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)