专栏文章

P1853 投资的最大效益

算法·理论参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minpoz94
此快照首次捕获于
2025/12/02 06:19
3 个月前
此快照最后确认于
2025/12/02 06:19
3 个月前
查看原文
本题为完全背包的模板题,只是如果要过hack需要一些特殊处理
一种错误情况:在基本的完全背包外加一个循环for1nfor_{1\sim n}使其符合题意
CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn(1e6+10);
int s,n,d;
int w[maxn],v[maxn],dp[maxn];
int main(){
    cin>>s>>n>>d;
    for(int i(1);i<=d;i++){
        cin>>w[i]>>v[i];
    }
    for(int i(1);i<=n;i++){
        for(int j(1);j<=d;j++){
            for(int k(w[j]);k<=s;k++){
                if(k>=(w[j])){
                    dp[k]=max(dp[k],dp[k-(w[j])]+v[j]);
                }
            }
        }
        s+=dp[m];
        memset(dp,0,sizeof(dp));
    }
    cout<<s<<'\n';
}
提交后发现hack过不去TLE
经过观察可以发现a是1000的倍数 也就是说a1000a\ge 1000所以dp11000dp_{1\sim1000}几乎没有意义,那么如果将这一段没用的区间省略掉,这样就可以使memset的复杂度降低
既然a是1000的倍数那么在计算dp时除1000,就可以省略掉多余空间降低时间
CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn(1e6+10);
int s,n,d;
int w[maxn],v[maxn],dp[maxn];
int main(){
    cin>>s>>n>>d;
    for(int i(1);i<=d;i++){
        cin>>w[i]>>v[i];
    }
    for(int i(1);i<=n;i++){
        int m(s/1000);
        for(int j(1);j<=d;j++){
            for(int k(w[j]/1000);k<=m;k++){
                if(k>=(w[j]/1000)){
                    dp[k]=max(dp[k],dp[k-(w[j]/1000)]+v[j]);
                }
            }
        }
        s+=dp[m];
        memset(dp,0,sizeof(dp));
    }
    cout<<s<<'\n';
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...