zoukankan      html  css  js  c++  java
  • 探讨人生 【贪心】

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

    本蒟蒻谢谢大家观看

    题目:

    探讨人生
    (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 */
     
     
  • 相关阅读:
    10.6比赛 T1
    10.5比赛 T3
    10.5比赛 T2
    10.5比赛 T1
    最大子序列问题
    Python编程快速上手_第 4 章 列表
    Python编程快速上手_第 3 章 函数
    Python编程快速上手_第 2 章 控制流
    Python编程快速上手_第 1 章 Python基础
    Python 编程快速上手 ——让繁琐工作自动化
  • 原文地址:https://www.cnblogs.com/nlyzl/p/11660569.html
Copyright © 2011-2022 走看看