求最大值

#include <bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
int a[1000],b[1000],ans=0,dp[101][200000+10],n,off=100000;//直接偏移,省事
//有两个量互相制约,两个量都单独的条件,这种类型,可以假设一个量不变然后dp数组,dp数组的值是b的最优值,这样通过一个数组把a的和,b的和联系在一起
//类似于多线程dp,这个不是完全的并行问题,但是有两个量
//可以滤过aibi都<0的值
//dp数组的第二维度不一定是正的,所以需要+偏移量变成正的,例如前面a都是<0但是最后一个很大>0,
//如果dp数组的第二维度都是正的,那么前面都是无效,只能选最后一个,但是这不一定是最优解
//但是怎么获得最优解呢?因为dpij中的j的值不一定是合法的,所以我们用-INF初始化,不用0(因为最终结果可能是0),这样只要dp数组>=0那么就是合法值,然后max即可
//因为以前是对dp数组求最大值,所以不用考虑,但是现在是对dp+j求最大值。。。。。
int main() {
    cin>>n;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=2*off;j++) dp[i][j]=-INF;
    for(int i=1;i<=n;i++){
        cin>>a[i]>>b[i];
        //类型的常规初始化方法,这是只有i的情况
        //其实也可以不用这么初始化
        // dp[i][a[i]+off]=b[i];
    }
    //三种情况,只有i,有其他,只有其他
    for(int i=1;i<=n;i++){
        for(int j=-off;j<=off;j++){
            // dp[i][j+off]=max(dp[i-1][j+off],dp[i][j+off]);//因为有只有i的情况,所以max
            dp[i][j+off]=dp[i-1][j+off];
            if(j+off<a[i]||j+off-a[i]>200000) continue;

            if(j==a[i]) dp[i][j+off]=max(b[i],dp[i][j+off]);//注意这句,最开始初始化是可以的,这样就必须 max(dp[i-1][j+off],dp[i][j+off]),
            // 但是明明后面的循环带了只有i的情况啊,观察发现,因为初值是inf,导致dp[i-1][j-a[i]+off]+b[i]没法更新所以单独讨论即可,
            // 这样前面就是dp[i][j+off]=dp[i-1][j+off];,总之不能忽略只有i的情况

            //这个必须考虑,因为a[i]可能是负的,如-2,导致在j=99999时超过限制,然后dp[i-1][j-a[i]+off]用到了超限的dp值,而那个值没初始化。。。
            dp[i][j+off]=max(dp[i][j+off],dp[i-1][j-a[i]+off]+b[i]);
            if(dp[i][j+off]>=0&&j>=0){
                ans=max(ans,dp[i][j+off]+j);
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2020-06-06 21:01  西伯利亚挖土豆  阅读(256)  评论(0编辑  收藏  举报