求最大值
#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; }