第k大可以多加一维状态
对于第i个物品 每次求出不放这个物品的时候 第1到第k大的数 就是上一维的情况 再求出放这个物品时候第1到第k大的数 得到2*k个价值 求出2*k个数中最大的k个
然后题目要求严格递减 不能一样
#include <cstdio>
#include <cstring>
const int maxn = 110;
int dp[maxn][maxn*10][33];
int a[maxn], b[maxn];
int x[maxn], y[maxn];
int main()
{
int T;
int n, m, t;
scanf("%d", &T);
while(T--)
{
scanf("%d %d %d", &n, &m, &t);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for(int i = 1; i <= n; i++)
scanf("%d", &b[i]);
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i++)
{
for(int j = 0; j <= m; j++)
{
if(j < b[i])
{
for(int k = 1; k <= t; k++)
{
dp[i][j][k] = dp[i-1][j][k];
}
}
else
{
for(int k = 1; k <= t; k++)
{
x[k] = dp[i-1][j-b[i]][k]+a[i];
y[k] = dp[i-1][j][k];
}
x[t+1] = y[t+1] = -1000000;
int i1 = 1, i2 = 1, i3 = 1;
while(i1 <= t && (i2 <= t || i3 <= t))
{
if(x[i2] > y[i3])
{
dp[i][j][i1] = x[i2];
i2++;
}
else
{
dp[i][j][i1] = y[i3];
i3++;
}
if(dp[i][j][i1] != dp[i][j][i1-1])
i1++;
}
}
}
}
printf("%d\n", dp[n][m][t]);
}
return 0;
}