其实原本让我补这些结训题我是拒绝的 尼玛能好好起名字么= =
不过看在第一次接触这知识点 知识点就补了吧 背包九讲以前就看完前三 补这题顺便也把后几讲学了学
第k大就是多了一维度 存放第1,2....k大 每次更新先把所有转移后的价值放进队列 然后队列前k大就是这次转移后的值 挨个存入即可
由于这题就要第2小 没用队列直接上if...
代码如下:
#include <bits/stdc++.h>
using namespace std;
int dp[1111][2];
int main()
{
int t,n,m,i,j,p,c;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
memset(dp,0,sizeof(dp));
for(i = 0; i < m; ++i)
{
scanf("%d %d",&c,&p);
for(j = n; j >= c; --j)
{
if(dp[j-c][0]+p > dp[j][0])
{
if(dp[j][0] > dp[j-c][1]+p)
{
dp[j][1] = dp[j][0];
}
else if(dp[j-c][1]+p < dp[j-c][0]+p && dp[j-c][1]+p > dp[j][1])
{
dp[j][1] = dp[j-c][1]+p;
}
dp[j][0] = dp[j-c][0]+p;
}
else if(dp[j-c][0]+p != dp[j][0] && dp[j-c][0]+p > dp[j][1])
{
dp[j][1] = dp[j-c][0]+p;
}
else if(dp[j-c][1]+p != dp[j][0] && dp[j-c][1]+p > dp[j][1])
{
dp[j][1] = dp[j-c][1]+p;
}
// printf("%d:%d %d\n",j,dp[j][0],dp[j][1]);
}
}
printf("%d\n",dp[n][0]+dp[n][1]);
}
return 0;
}