标签:space 评测 开始 有一个 怎么 using std 记录 一个
这是完全背包。
而且是加了点东西的完全背包。
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完毕。
#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;
}
标签:space 评测 开始 有一个 怎么 using std 记录 一个
原文地址:https://www.cnblogs.com/FUXyao/p/12927061.html