输入
输入第一行包含三个正整数n,m,t,代表商店物品的数量,鸡尾酒带的钱,和询问的次数。(n,m<=2000,t<=3000)
接下来n行,每行输入两个正整数,分别代表第i个物品在平常的价格ai和价值bi。(ai<=m, bi<=1e9)
接下来有t组询问,每组询问包含三个数字,x,c,d。代表某一天第x个物品参与“特别活动”,并且价格变为c,价值变为d。(c<=m,d<=1e9)
输出
对于每组询问,回答鸡尾酒那一天可以购买的物品最大价值和。
3 10 3
1 2
5 10
4 9
1 3 8
2 3 5
3 4 5
19
16
17
正反各预处理一遍01背包 O(n*m)
t组样例 只能O(m)
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define pb push_back
#define mp make_pair
#define IO ios::sync_with_stdio(false)
#define fi first
#define se second
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=2e5+5;
const int maxm=1e6+5;
const ll INF=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
ll w[2005],v[2005],ans1,ans2;
ll pre[2005][2005],suf[2005][2005];
int n,m,t,x,c,d;
int main(){
cin>>n>>m>>t;
rep(i,1,n){
cin>>w[i]>>v[i];
}
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++)
if(w[i]<=j)
pre[i][j]=max(pre[i-1][j],pre[i-1][j-w[i]]+v[i]);
else
pre[i][j]=pre[i-1][j];
}
for(int i=n;i>=1;i--){
for(int j=0;j<=m;j++)
if(w[i]<=j)
suf[n-i+1][j]=max(suf[n-i][j],suf[n-i][j-w[i]]+v[i]);//背包装的第一个物品是原先第n个
else
suf[n-i+1][j]=suf[n-i][j];
}
while(t--){
ans1=0,ans2=0;
cin>>x>>c>>d;
for(int j=0;j<=m;j++)
ans1=max(pre[x-1][j]+suf[n-x][m-j],ans1); //不装当前第x个物品 n=3 x=2 装第一个 和 倒数第一个
for(int j=0;j<=m-c;j++) //要当前第x个物品 背包空间腾出c
{
ans2=max(pre[x-1][j]+suf[n-x][m-c-j],ans2);
}
cout<<max(ans1,ans2+d)<<endl;
}
return 0;
}
用到中间的pre,suf的dp值 所以else递推不能省略 否则会wa
如果直接求dp[n][m] dp方程可以不用管else递推