探讨人生 贪心

Posted nlyzl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了探讨人生 贪心相关的知识,希望对你有一定的参考价值。

 

本人水平有限,题解不到为处,请多多谅解

 

本蒟蒻谢谢大家观看

 

题目:

探讨人生
(life.cpp/in/out 1s 256M)
Smart每次他与好友A探讨人生要花费a个小时,并可以得到x点人生经验;每次与好友B探讨人生要花费b个小时,并
得到y点人生经验。但是Smart的精力是有限的,他只能抽出n个小时来跟他的友人们探讨人生,若这n个小时并没有
被用完,则Smart会把剩下的时间拿来跟好友C聊天,而这并不能得到人生经验。现在Smart想知道,他最多可以得
到多少点人生经验
Input
输入共1行
包含5个整数n、x、y、a、b,每两个整数之间用一个空格隔开。
Output
输出共1行,包含1个整数,表示Smart最多能得到的人生经验。
Sample Input
999999999 999999998 5 999999999 5
Sample Output
999999998
 
题目意思有点没说清楚,导致只有50分。
大意如下只要n>a||n>b就可以继续累加人生经验,不能只加一次x,y就完事了(就因为这样惨淡30分)
 
本题为典型的贪心,但贪心策略很难想到。以至于看了题解以后的(ruoji)我还是没完全弄明白。
SOl:

首先设平均每小时获得的贡献较多的那个为A,另一个为B也就是说A较划算。那么分两种情况讨论:

,那么直接暴力枚举A用了几次,时间复杂度为O(√n)

我们枚举B用了几次,注意B用的次数一定小于A,否则我们可以用b个A替换a个B,得到一种更优的方案。

时间复杂度为O(√n)

 

先说这一段

if(x*b<y*a) 
    swap(x,y),swap(a,b);

是由x/a与y/b比较,为了求单位时间内 A的贡献与B的贡献的大小。这里强制认为 A的贡献较大,所以交换。

 

接下来是这一段:

LL ans=0;
      if(a>=n/a){//a>sqrt(n),枚举与A探讨0~n/a次 
           for(int i=0; i*a<=n; i++) //枚举与好友A探讨i 
               ans=max(ans,i*x+(n-i*a)/b*y); 
    }  
    else{ 
    //a<sqrt(n),枚举与B探讨0~a次,因为若与B次数>=a,则可以把其中a次换成与A的b次一定更优
        for(int i=0; i*b<=n&&i<a; i++){
            ans=max(ans,i*y+(n-i*b)/a*x);    
        }    
    }

为什么要判断(a>=n/a)呢?通过实测样例可知:如果不特判的话,时间复杂度为O(N),看一下数据也知道会TLE

所以采用节省时间的优化方案,将时间复杂度减至O(√N)。

既然已经使用了优化,那么就有两种情况
1:直接暴力枚举与A好友探讨时所得到的最大贡献值。

2:采用逆向思维,我们既然已经穷举完A,自然就要枚举B了。注意:在枚举B时,与B好友探讨时间次数必须小于a。如果次数超过a的话,就不是最优解了,因为单位时间B的贡献值小于A的(之前我们已经强制规定),

相当于     一个小的值*一个大的次数+一个大的值*一个小的次数 < 大值*大次数+小值*小次数。已然不是最大值

 

最后上代码:
code:
 1 #include <bits/stdc++.h> 
 2 #define LL long long 
 3 using namespace std; 
 4 LL n,x,y,a,b; 
 5 void init(){ 
 6     cin>>n>>x>>y>>a>>b; 
 7     if(x*b<y*a) 
 8     swap(x,y),swap(a,b);
 9 }
10 void work(){ 
11      LL ans=0;
12       if(a>=n/a){//a>sqrt(n),枚举与A探讨0~n/a次 
13            for(int i=0; i*a<=n; i++) //枚举与好友A探讨i 
14                ans=max(ans,i*x+(n-i*a)/b*y); 
15     }  
16     else{ 
17     //a<sqrt(n),枚举与B探讨0~a次,因为若与B次数>=a,则可以把其中a次换成与A的b次一定更优
18         for(int i=0; i*b<=n&&i<a; i++){
19             ans=max(ans,i*y+(n-i*b)/a*x);    
20         }    
21     }
22     printf("%lld",ans); 
23 }
24 int main() 
25 { 
26     init(); 
27     work(); 
28     return 0; 
29 }
30 /*
31 10 3 5 2 3
32 10 3(x) 5(y) 2(a) 3(b)
33 10 5(x) 3(y) 3(a) 2(b)
34 */

 

 
 

以上是关于探讨人生 贪心的主要内容,如果未能解决你的问题,请参考以下文章

人生战略(清醒贪心记公众号摘抄)

硬核人生!华人教授遭持枪劫车!靠“贪心算法”追回秒杀美国警察~

贪心算法:划分字母区间

763. 划分字母区间-贪心算法

推荐net开发cad入门阅读代码片段

贪心热门问题8:划分字母区间