本人水平有限,题解不到为处,请多多谅解
本蒟蒻谢谢大家观看
题目:
探讨人生
(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,每两个整数之间用一个空格隔开。
(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
输出共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 */