POJ2586 Y2K Accounting Bug (贪心,比较好玩的想法)
题意:某家公司,一年内每个月都会盈利或亏损,而且盈利或亏损都是一个定值,要么盈利s元,要么亏损d元,已知这一年内,这家公司任意连续五个月的总业绩都是亏损的,但全年统计下来并不见得亏损,问这家公司一年最多盈利多少元,如果不可能盈利,输出Deficit;
对于这道题我们会想到搜索,去枚举下一个月怎么填盈亏,然后最终求得最优解,但是实际上我们题目中给的条件很有意思,我们可以单单在题目条件上做文章,从而贪心求解:
这个题换句话说就是要在满足条件的情况下,使亏损的月份出现次数尽可能少。我们可以以五个月为单位,在这五个月中,亏损最少出现多少次,能保证这五个月总和是亏损的,那我们就以这五个月为一个循环节,以此规划全年的盈亏。这个方法乍一想觉得有些不妥,那我们手动观察一下:就拿样例来看:
59 59 59 59 237 59 59 59 59 237 这是十个月的循环;
375 375 375 743 743 375 375 375 743 743 这是十个月的循环;
是不是发现我只要把盈利都放前面,亏损都放后面,这样的循环是绝对符合条件的,然后不是还有两个月呢么,那就直接判断后面两个月是否可以都盈利,如果可以直接都盈利,如果不能按照最大盈利的条件贪心去放置。其实我们发现,前10个月是不可能盈利的,所有的盈利全靠最后两个月的最大化。统计最终结果时,看看究竟可不可能盈利,这道题就做完了:
还有一点,亲测,其实盈亏为零到底算盈利还是算亏损对题目没有影响,数据也没有设这种有争议的东西,大胆写就好
上代码:
1 #include<iostream> 2 #include<cmath> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<string> 7 #include<cstdio> 8 #include<queue> 9 using namespace std; 10 int n,m,p,q,s,d; 11 int main() 12 { 13 while(~scanf("%d%d",&s,&d)){ 14 int i; 15 for(i=0;i*s-(5-i)*d<0;i++);i--; 16 int ans=i*s-(5-i)*d;ans*=2; 17 if(i>=2) ans+=2*s; 18 else ans=ans+i*s-(2-i)*d; 19 if(ans>=0) cout<<ans<<endl; 20 else puts("Deficit"); 21 } 22 return 0; 23 }