这个dp以前没见过 确实不会 怎么才能保证两两互不相交呢 在我印象里面没有这样操作过的dp
考虑换个想法 设dp[i,j,k]表示 前i个 两者差值为j 用了k次加倍 因为下标不能为负 所以整体向右偏移1300
初始化 dp[0,1300,0]=0 答案 max{dp[n,1300,i]} i属于[0,k]
转移方程:dp[i,j,k]=max(dp[i-1,j+v[i],k]+w[i],dp[i-1,j-v[i],k]+w[i],dp[i-1,j+2v[i],k-1]+w[i],dp[i-1,j-2v[i],k-1]+w[i])
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int N=103;
typedef long long ll;
ll f[N][3003][N],w[N],v[N];
int main()
{
memset(f,-0x3f,sizeof f);
f[0][1300][0]=0;
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
scanf("%lld%lld",&w[i],&v[i]);
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
for(int k=0;k<=2600;k++)
{
f[i][k][j]=f[i-1][k][j];
if(k>=2*v[i]&&j>=1)
f[i][k][j]=max(f[i][k][j],f[i-1][k-2*v[i]][j-1]+w[i]);
if(k>=v[i])
f[i][k][j]=max(f[i][k][j],f[i-1][k-v[i]][j]+w[i]);
if(k+2*v[i]<=2600&&j>=1)
f[i][k][j]=max(f[i][k][j],f[i-1][k+2*v[i]][j-1]+w[i]);
if(k+v[i]<=2600)
f[i][k][j]=max(f[i][k][j],f[i-1][k+v[i]][j]+w[i]);
}
ll ans=-0x3f3f3f3f;
for(int i=0;i<=m;i++)
ans=max(ans,f[n][1300][i]);
cout<<ans;
return 0;
}