P1853 投资的最大效益
Posted fuxyao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1853 投资的最大效益相关的知识,希望对你有一定的参考价值。
题目:
大致题意:
-
这是完全背包。
-
而且是加了点东西的完全背包。
-
f[i]表示总资产i的最大利息值。
-
按照完全背包的模板来n次就能找出正确答案。
-
在完全背包的循环执行完毕后则需要用s加上f[s],因为f[s]只是总资产s的利息。
-
那么代码便是:
for(int i=1;i<=n;++i){ for(int j=1;j<=d;++j){ for(int k=w[j];k<=s;++k){ f[k]=max(f[k],f[k-w[j]]+v[j]); } } s+=f[s]; }
-
但是评测记录告诉我们,TLE了。。
-
虽然只有一个点TLE,但他就是TLE了!
-
所以我们需要优化,怎么优化呢?
我也不知道 -
在说明/提示里有段话说的是且a是1000的倍数,根据这句话我们就可以做出优化了。
-
怎么根据这个优化呢?既然a是1000的倍数,那么在上述代码中的k变量在循环中就可以做出相应的整改了。
-
因为a就是上述代码里面的w[j],所以k一开始就是w[j],也就是说k一开始是1000的倍数。
-
那么在下面的公式中,如果k是1001也不会与1000有什么不同,也就是说只要k不是1000的倍数的时候,里面的公式做的都是无用功,浪费了很多时间。
-
既然这样,那么我们就可以把
++k
改为k+=1000
,这样就可以省下了不少的时间。 -
但是这样还是有些bug,这bug并不是指时间问题,而是指
s+=f[s]
上,因为s有可能不是1000的倍数,那么就会加上一些奇奇怪怪的数,导致WA掉。 -
所以就需要改一改,怎么改呢,既然s并没有被遍历到,但是s的利息和s-s%1000的利息一样,所以把
s+=f[s]
中的f[s]
改为f[s-s%1000]
就好了。 -
至此dp完毕。
Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
using namespace std;
#define R read()
#define GC getchar()
#define ll long long
#define ull unsigned long long
#define INF 0x7fffffff
#define LLINF 0x7fffffffffffffff
ll read(){
ll s=0,f=1;
char c=GC;
while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-f;c=GC;}
while(c>=‘0‘&&c<=‘9‘){s=s*10+c-‘0‘;c=GC;}
return s*f;
}
int s,n,d;
int w[20],v[20];
int f[10000010];
int main(){
s=R;n=R;d=R;
for(int i=1;i<=d;++i){//输入
w[i]=R;v[i]=R;
}
for(int i=1;i<=n;++i){//投资n年
for(int j=1;j<=d;++j){//完全背包的模板
for(int k=w[j];k<=s;k+=1000){
f[k]=max(f[k],f[k-w[j]]+v[j]);//平平无奇的转换公式
}
}
s+=f[s-s%1000];//加上利息
}
printf("%d",s);//输出
return 0;
}
以上是关于P1853 投资的最大效益的主要内容,如果未能解决你的问题,请参考以下文章